"use client";

import React, { useEffect, useRef, useState, useCallback} from "react";
import { Container, Row, Col, Card, Form, FloatingLabel, Button, Stack, Spinner } from "react-bootstrap";
import { useForm } from "react-hook-form";
import { useToast } from "@/context/ToastContext";
import LoadingCMS from "@/components/LoadingCMS";
import Link from "next/link";
import { FileTypes } from "@/lib/types";
import { useRecaptcha } from "@/hooks/useRecaptcha";

type MetaForm = {
  sm_id: number;
  sm_path: string;
  sm_title: string;
  sm_description: string;
  sm_schema: string;
  sm_type: string;
  sm_photo?: FileList;
};
type MetaData = MetaForm & {
  sm_file: FileTypes | null;
};
const allowedOgTypes = ["website", "article", "book", "profile"] as const;

export default function Seo() {
  const { showToast } = useToast();
  const { getToken } = useRecaptcha();

  const [metas, setMetas] = useState<MetaData[]>([]);
  const [metaLoading, setMetaLoading] = useState(true);
  const [selectedMeta, setSelectedMeta] = useState<MetaData | null>(null);
  const [search, setSearch] = useState("");
  const fileInputRef = useRef<HTMLInputElement | null>(null);

  const {register,handleSubmit,reset,formState:{errors,isSubmitting} } = useForm<MetaForm>({defaultValues:{sm_id:0,sm_path:"",sm_title:"",sm_description:"",sm_schema:"",sm_type:"",sm_photo:undefined}});

  const fetchAllMeta = useCallback(async () => {
    try {
      const res = await fetch("/api/meta/list");
      const json = await res.json();
      if (res.ok && Array.isArray(json.metaWithFile)) {
        setMetas(json.metaWithFile);
      }
    } 
    catch { showToast("Meta List: Getting failed..", "danger"); }
    finally { setMetaLoading(false); }
  }, [showToast]);
  useEffect(() => {
    fetchAllMeta();
  }, [fetchAllMeta]);

  useEffect(() => {
    if (selectedMeta) {
      let formattedSchema = "";

      try {
        if (selectedMeta.sm_schema) {
          formattedSchema = JSON.stringify(
            JSON.parse(selectedMeta.sm_schema),
            null,
            2 // pretty format
          );
        }
      } catch (e) {
        console.error("Schema parse error:", e);
        formattedSchema = selectedMeta.sm_schema || "";
      }

      reset({
        ...selectedMeta,
        sm_schema: formattedSchema,
      });
    }
  }, [selectedMeta, reset]);

  const filteredMetas = metas.filter(meta =>
    meta.sm_title.toLowerCase().includes(search.toLowerCase()) || 
    meta.sm_description.toLowerCase().includes(search.toLowerCase()) || 
    meta.sm_path.toLowerCase().includes(search.toLowerCase())
  );

  const onSubmit = async (data: MetaForm) => {
    try {
      const recaptchaToken = await getToken("meta_save_form");
      const formData = new FormData();
      formData.append("sm_id", String(data.sm_id || 0));
      formData.append("sm_path", data.sm_path);
      formData.append("sm_title", data.sm_title);
      formData.append("sm_description", data.sm_description);
      formData.append("sm_schema", data.sm_schema);
      formData.append("sm_type", String(data.sm_type));
      if (data.sm_photo && data.sm_photo.length > 0 && data.sm_photo[0] instanceof File) {
        formData.append("sm_photo", data.sm_photo[0]);
      }
      formData.append("recaptchaToken", recaptchaToken || '');
      const res = await fetch("/api/meta/save", {
        method: "POST",
        body: formData
      });
      const result = await res.json();
      if (res.ok) {
        showToast(result.message, "success");
        reset({
          sm_id: 0,
          sm_path: "",
          sm_title: "",
          sm_description: "",
          sm_schema: "",
          sm_type: "",
        });
        if (fileInputRef.current) {
          fileInputRef.current.value = "";
        }
        setSelectedMeta(null);
        fetchAllMeta();
      } 
      else { showToast(result.error, "danger"); }
    } catch { showToast("Meta Save: Failed to save.", "danger"); }
  };
  const deleteMeta = async (sm_id: number) => {
    if (!confirm("Are you sure you want to delete this meta?")) return;

    try {
      const res = await fetch(`/api/meta/delete?smId=${sm_id}`, {
        method: "DELETE",
      });
      const result = await res.json();

      if (res.ok) {
        showToast(result.message, "success");
        fetchAllMeta();
      } else {
        showToast(result.error, "danger");
      }
    } catch {
      showToast("Meta Delete: Failed to delete.", "danger");
    }
  };
  if (metaLoading) return <LoadingCMS />;

  return (
    <Container fluid className="py-3">
      <Row>        
        <Col md={8}>
          <Row xs={1} md={2} className="g-3">
            <Col md={3} className="align-self-center">
              <h1 className="fs-3">Metas <small className="text-body-secondary">({filteredMetas.length})</small></h1>
            </Col>
            <Col md={5}>
              <FloatingLabel label="Search by title or path">
                <Form.Control value={search} onChange={(e) => setSearch(e.target.value)} />
              </FloatingLabel>
            </Col>
            <Col md={2} className="align-self-center">
              <Link href="/sitemap.xml" target="_blank" rel="noopener noreferrer" className="btn btn-lg btn-outline-primary rounded-pill w-100">Sitemap</Link>
            </Col>
            <Col md={2} className="align-self-center">
              <Link href="/robots.txt" target="_blank" rel="noopener noreferrer" className="btn btn-lg btn-outline-dark rounded-pill w-100">Robots</Link>
            </Col>
            {filteredMetas.map((meta, index) => (
              <Col key={index}>
                <Card className={`h-100 rounded-4 ${selectedMeta && selectedMeta.sm_path === meta.sm_path ? 'text-bg-success' : null}`}>
                  {meta.sm_file && meta.sm_file.up_id > 0 ? (
                    <Card.Img src={meta.sm_file.src} alt={meta.sm_title} width={meta.sm_file.up_width} height={meta.sm_file.up_height} className="img-fluid rounded-4" />
                  ) : null}                  
                  <Card.Body>
                    <Card.Title>{meta.sm_path}</Card.Title>
                    <Card.Subtitle className="mb-2 text-muted">{meta.sm_title}</Card.Subtitle>
                    <Card.Text>{meta.sm_description}</Card.Text>              
                  </Card.Body>
                  <Card.Footer className="d-flex align-items-center justify-content-between">
                    {meta.sm_schema ? <span className="badge bg-success">Schema</span> : <span className="badge bg-warning ms-2">Schema</span>}
                    {meta.sm_type && <span className="badge bg-primary mx-3">{meta.sm_type}</span>}                    
                    <Button variant="outline-danger" className="rounded-pill flex-fill" onClick={() => setSelectedMeta(meta)}>Edit</Button>
                    <Button variant="danger" className="rounded-pill ms-3" onClick={ () => deleteMeta(meta.sm_id)}>DEL</Button>
                  </Card.Footer>
                </Card>
              </Col>
            ))}
          </Row>
        </Col>
        <Col md={4} className="position-sticky vh-100 overflow-y-auto" style={{ top: "1rem" }}>
          <Card className="rounded-4 bg-light">            
            <Card.Body>
              <h4 className="mb-4">{selectedMeta ? "Edit Meta" : "Create New Meta"}</h4>
              <Form noValidate onSubmit={handleSubmit(onSubmit)}>
                <Row className="g-3">
                  <Col md={12}>                               
                    <FloatingLabel label="Meta Type">
                      <Form.Select aria-label="Floating label select example" {...register("sm_type", { required: "Type is required" })} isInvalid={!!errors.sm_type}>
                        <option value="">Please Select</option>
                        {allowedOgTypes.map((type) => (
                          <option key={type} value={type}>
                            {type}
                          </option>
                        ))}
                      </Form.Select>
                      <Form.Control.Feedback type="invalid">{errors.sm_type?.message}</Form.Control.Feedback>
                    </FloatingLabel>
                  </Col>
                  <Col md={12}>
                    <FloatingLabel label="Canonical Path (Exclude : https://vensysco.com)">
                      <Form.Control {...register("sm_path", { required: "Path is required" })} isInvalid={!!errors.sm_path} />
                      <Form.Control.Feedback type="invalid">{errors.sm_path?.message}</Form.Control.Feedback>
                    </FloatingLabel>
                  </Col>
                  <Col md={12}>
                    <FloatingLabel label="Title">
                      <Form.Control {...register("sm_title", { required: "Title is required" })} isInvalid={!!errors.sm_title} />
                      <Form.Control.Feedback type="invalid">{errors.sm_title?.message}</Form.Control.Feedback>
                    </FloatingLabel>
                  </Col>
                  <Col md={12}>
                    <FloatingLabel label="Description">
                      <Form.Control as="textarea" rows={3} {...register("sm_description", { required: "Description is required" })} isInvalid={!!errors.sm_description} />
                      <Form.Control.Feedback type="invalid">{errors.sm_description?.message}</Form.Control.Feedback>
                    </FloatingLabel>
                  </Col>
                  <Col md={12}>
                    <FloatingLabel label="Schema (JSON-LD)">
                      <Form.Control as="textarea" rows={5} {...register("sm_schema")} style={{ fontFamily: "monospace" }} isInvalid={!!errors.sm_schema} />
                      <Form.Control.Feedback type="invalid">{errors.sm_schema?.message}</Form.Control.Feedback>
                    </FloatingLabel>
                  </Col>
                  <Col md={12}>
                  {selectedMeta ? (
                    <FloatingLabel label="Upload Photo">
                      <Form.Control type="file" accept=".webp,.png,.jpg,.jpeg" {...register("sm_photo")} ref={(e) => { register("sm_photo").ref(e);fileInputRef.current = e; }} isInvalid={!!errors.sm_photo}/>
                      <Form.Control.Feedback type="invalid">{errors.sm_photo?.message}</Form.Control.Feedback>
                    </FloatingLabel>
                  ) : (
                    <FloatingLabel label="Upload Photo">
                      <Form.Control type="file" accept=".webp,.png,.jpg,.jpeg" {...register("sm_photo", { required: "Photo is required" })} ref={(e) => { register("sm_photo").ref(e);fileInputRef.current = e; }} isInvalid={!!errors.sm_photo}/>
                      <Form.Control.Feedback type="invalid">{errors.sm_photo?.message}</Form.Control.Feedback>
                    </FloatingLabel>
                  )}                    
                  </Col>                  
                  <Col md={12}>
                    <Stack direction="horizontal" gap={3}>
                      <Button type="submit" variant="danger" className="w-100 rounded-pill" disabled={isSubmitting}>
                        {isSubmitting ? (
                          <Stack gap={2} direction="horizontal">
                            <Spinner animation="grow" size="sm" variant="danger" />
                            <Spinner animation="grow" size="sm" variant="primary" />
                            <Spinner animation="grow" size="sm" variant="success" />
                            <span>{ selectedMeta ? 'Updating...' : 'Creating...'}</span>
                          </Stack>
                        ) : selectedMeta ? "Update Meta" : "Create Meta"}
                      </Button>
                      {selectedMeta && (
                        <Button variant="outline-secondary" className="w-100 rounded-pill" onClick={() => {reset();setSelectedMeta(null);}}>
                          Cancel Edit
                        </Button>
                      )}
                    </Stack>
                  </Col>
                </Row>
              </Form>
            </Card.Body>
          </Card>
        </Col>
      </Row>
    </Container>
  );
}
