import { useMemo, useState, useEffect } from "react";
import { Link, useNavigate, useSearchParams } from "react-router-dom";
import {
  ArrowLeft,
  Download,
  Edit3,
  Grid,
  Image,
  Layout,
  Plus,
  Settings,
  Table,
  Trash2,
} from "react-feather";

import { putJson, request } from "../lib/api";
import {
  BUILTIN_PAGE_TEMPLATES,
  createCustomTemplateId,
  mergePageTemplates,
} from "../lib/pageTemplates";
import { ensureSections, flattenSections } from "../lib/sections";
import { buildSessionQuery, getSessionId, setStoredSessionId } from "../lib/session";
import type { JobsheetSection, PageTemplateDefinition, Session } from "../types/session";
import { InfoMenu } from "../components/InfoMenu";
import { PageFooter } from "../components/PageFooter";
import { PageHeader } from "../components/PageHeader";
import { PageShell } from "../components/PageShell";

type Variant = "full" | "photos";
type PhotoLayout = "auto" | "two-column" | "stacked";

const DEFAULT_VARIANT: Variant = "full";
const DEFAULT_PHOTO_LAYOUT: PhotoLayout = "auto";

export default function LayoutTemplatesPage() {
  const [searchParams] = useSearchParams();
  const sessionId = getSessionId(searchParams.toString());
  const sessionQuery = buildSessionQuery(sessionId);
  const navigate = useNavigate();

  const [session, setSession] = useState<Session | null>(null);
  const [sections, setSections] = useState<JobsheetSection[]>([]);
  const [templates, setTemplates] = useState<PageTemplateDefinition[]>(
    BUILTIN_PAGE_TEMPLATES,
  );
  const [customTemplates, setCustomTemplates] = useState<PageTemplateDefinition[]>(
    [],
  );

  const [newName, setNewName] = useState("");
  const [newDescription, setNewDescription] = useState("");
  const [newVariant, setNewVariant] = useState<Variant>(DEFAULT_VARIANT);
  const [newPhotoLayout, setNewPhotoLayout] =
    useState<PhotoLayout>(DEFAULT_PHOTO_LAYOUT);
  const [newBlank, setNewBlank] = useState(false);
  const [status, setStatus] = useState("");
  const [isSaving, setIsSaving] = useState(false);

  useEffect(() => {
    if (!sessionId) {
      setStatus("No active session found.");
      return;
    }
    setStoredSessionId(sessionId);
    async function load() {
      try {
        const [data, sectionResp] = await Promise.all([
          request<Session>(`/sessions/${sessionId}`),
          request<{ sections: JobsheetSection[] }>(`/sessions/${sessionId}/sections`),
        ]);
        setSession(data);
        setSections(ensureSections(sectionResp.sections));
        const merged = mergePageTemplates(data.page_templates);
        setTemplates(merged);
        setCustomTemplates(merged.filter((template) => template.source === "custom"));
      } catch (error) {
        const message =
          error instanceof Error ? error.message : "Failed to load templates.";
        setStatus(message);
      }
    }
    load();
  }, [sessionId]);

  const flatPages = useMemo(
    () => flattenSections(ensureSections(sections)),
    [sections],
  );

  const saveTemplates = async (nextTemplates: PageTemplateDefinition[]) => {
    if (!sessionId) return;
    setIsSaving(true);
    setStatus("Saving templates...");
    try {
      const payload = nextTemplates.map((template) => ({
        id: template.id,
        name: template.name,
        description: template.description ?? "",
        blank: Boolean(template.blank),
        variant: (template.variant ?? DEFAULT_VARIANT) as Variant,
        photo_layout: (template.photo_layout ?? DEFAULT_PHOTO_LAYOUT) as PhotoLayout,
      }));
      const response = await putJson<{ page_templates: PageTemplateDefinition[] }>(
        `/sessions/${sessionId}/page-templates`,
        { page_templates: payload },
      );
      const merged = mergePageTemplates(response.page_templates);
      setTemplates(merged);
      setCustomTemplates(merged.filter((template) => template.source === "custom"));
      setSession((prev) =>
        prev
          ? { ...prev, page_templates: response.page_templates ?? payload }
          : prev,
      );
      setStatus("Templates saved.");
    } catch (error) {
      const message =
        error instanceof Error ? error.message : "Failed to save templates.";
      setStatus(message);
    } finally {
      setIsSaving(false);
    }
  };

  const addTemplate = async () => {
    const name = newName.trim();
    if (!name) {
      setStatus("Template name is required.");
      return;
    }
    const nextTemplate: PageTemplateDefinition = {
      id: createCustomTemplateId(),
      name,
      description: newDescription.trim(),
      blank: newBlank,
      variant: newVariant,
      photo_layout: newPhotoLayout,
      source: "custom",
    };
    await saveTemplates([...customTemplates, nextTemplate]);
    setNewName("");
    setNewDescription("");
    setNewVariant(DEFAULT_VARIANT);
    setNewPhotoLayout(DEFAULT_PHOTO_LAYOUT);
    setNewBlank(false);
  };

  const updateCustomTemplate = (
    templateId: string,
    patch: Partial<PageTemplateDefinition>,
  ) => {
    setCustomTemplates((prev) =>
      prev.map((template) =>
        template.id === templateId ? { ...template, ...patch } : template,
      ),
    );
  };

  const removeCustomTemplate = async (templateId: string) => {
    const next = customTemplates.filter((template) => template.id !== templateId);
    await saveTemplates(next);
  };

  const persistCustomTemplateEdits = async () => {
    await saveTemplates(customTemplates);
  };

  return (
    <PageShell>
      <PageHeader
        title="RepEx - Report Express"
        subtitle="Template Library"
        right={
          <div className="flex items-center gap-2">
            <Link
              to={`/edit-layouts${sessionQuery}`}
              className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
            >
              <ArrowLeft className="h-4 w-4" />
              Back
            </Link>
            <InfoMenu sessionQuery={sessionQuery} />
          </div>
        }
      />

      <nav className="mb-6" aria-label="Report workflow navigation">
        <div className="flex flex-wrap gap-2">
          <Link
            to={`/input-data${sessionQuery}`}
            className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
          >
            <Table className="h-4 w-4" />
            Input Data
          </Link>

          <Link
            to={`/report-viewer${sessionQuery}`}
            className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
          >
            <Layout className="h-4 w-4" />
            Report Viewer
          </Link>

          <Link
            to={`/image-placement${sessionQuery}`}
            className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
          >
            <Image className="h-4 w-4" />
            Image Placement
          </Link>

          <Link
            to={`/edit-report${sessionQuery}`}
            className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
          >
            <Edit3 className="h-4 w-4" />
            Edit Report
          </Link>

          <Link
            to={`/edit-layouts${sessionQuery}`}
            className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
          >
            <Grid className="h-4 w-4" />
            Edit Page Layouts
          </Link>

          <span className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-900 px-4 py-2 text-sm font-semibold text-white">
            <Settings className="h-4 w-4" />
            Template Library
          </span>

          <Link
            to={`/export${sessionQuery}`}
            className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
          >
            <Download className="h-4 w-4" />
            Export
          </Link>
        </div>
      </nav>

      <section className="mb-6 rounded-lg border border-gray-200 bg-white p-4">
        <h2 className="text-lg font-semibold text-gray-900">Current Usage</h2>
        <p className="text-sm text-gray-600">
          {sections.length} sections and {flatPages.length} pages currently use page templates.
        </p>
      </section>

      <section className="mb-6 rounded-lg border border-gray-200 bg-white p-4">
        <h2 className="text-lg font-semibold text-gray-900">Create Custom Template</h2>
        <p className="text-sm text-gray-600 mb-3">
          Define a reusable page template, name it, and apply it when adding pages in
          Edit Page Layouts.
        </p>
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
          <label className="text-sm text-gray-700">
            Template Name
            <input
              type="text"
              value={newName}
              onChange={(event) => setNewName(event.target.value)}
              className="mt-1 w-full rounded-md border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-200"
              placeholder="My Custom Template"
            />
          </label>
          <label className="text-sm text-gray-700">
            Variant
            <select
              value={newVariant}
              onChange={(event) => setNewVariant(event.target.value as Variant)}
              className="mt-1 w-full rounded-md border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-200"
            >
              <option value="full">Full</option>
              <option value="photos">Photos only</option>
            </select>
          </label>
          <label className="text-sm text-gray-700">
            Photo Layout
            <select
              value={newPhotoLayout}
              onChange={(event) =>
                setNewPhotoLayout(event.target.value as PhotoLayout)
              }
              className="mt-1 w-full rounded-md border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-200"
            >
              <option value="auto">Auto</option>
              <option value="two-column">Two column</option>
              <option value="stacked">Stacked</option>
            </select>
          </label>
          <label className="text-sm text-gray-700 md:col-span-2 lg:col-span-2">
            Description
            <input
              type="text"
              value={newDescription}
              onChange={(event) => setNewDescription(event.target.value)}
              className="mt-1 w-full rounded-md border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-200"
              placeholder="Optional notes for the template"
            />
          </label>
          <label className="inline-flex items-center gap-2 self-end text-sm text-gray-700">
            <input
              type="checkbox"
              checked={newBlank}
              onChange={(event) => setNewBlank(event.target.checked)}
            />
            Blank page
          </label>
        </div>
        <button
          type="button"
          onClick={() => {
            void addTemplate();
          }}
          disabled={isSaving}
          className="mt-4 inline-flex items-center gap-2 rounded-lg bg-emerald-600 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-700 transition disabled:opacity-50 disabled:cursor-not-allowed"
        >
          <Plus className="h-4 w-4" />
          Create template
        </button>
      </section>

      <section className="rounded-lg border border-gray-200 bg-white p-4">
        <div className="flex items-center justify-between gap-3 mb-3">
          <h2 className="text-lg font-semibold text-gray-900">Saved Templates</h2>
          <button
            type="button"
            onClick={() => {
              void persistCustomTemplateEdits();
            }}
            disabled={isSaving}
            className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition disabled:opacity-50 disabled:cursor-not-allowed"
          >
            Save edits
          </button>
        </div>

        <div className="space-y-3">
          {templates.map((template) => {
            const isCustom = template.source === "custom";
            return (
              <div
                key={template.id}
                className="rounded-lg border border-gray-200 bg-gray-50 p-3"
              >
                <div className="flex flex-wrap items-center justify-between gap-2">
                  <div className="text-xs font-semibold text-gray-500">{template.id}</div>
                  <span
                    className={[
                      "inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-semibold",
                      isCustom
                        ? "bg-emerald-50 text-emerald-700 border border-emerald-200"
                        : "bg-gray-100 text-gray-600 border border-gray-200",
                    ].join(" ")}
                  >
                    {isCustom ? "Custom" : "Built-in"}
                  </span>
                </div>
                <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-2 mt-2">
                  <label className="text-xs text-gray-600 lg:col-span-2">
                    Name
                    <input
                      type="text"
                      value={template.name}
                      disabled={!isCustom}
                      onChange={(event) =>
                        updateCustomTemplate(template.id, { name: event.target.value })
                      }
                      className="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-sm disabled:bg-gray-100 disabled:text-gray-500"
                    />
                  </label>
                  <label className="text-xs text-gray-600">
                    Variant
                    <select
                      value={template.variant ?? DEFAULT_VARIANT}
                      disabled={!isCustom}
                      onChange={(event) =>
                        updateCustomTemplate(template.id, {
                          variant: event.target.value as Variant,
                        })
                      }
                      className="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-sm disabled:bg-gray-100 disabled:text-gray-500"
                    >
                      <option value="full">Full</option>
                      <option value="photos">Photos only</option>
                    </select>
                  </label>
                  <label className="text-xs text-gray-600">
                    Photo Layout
                    <select
                      value={template.photo_layout ?? DEFAULT_PHOTO_LAYOUT}
                      disabled={!isCustom}
                      onChange={(event) =>
                        updateCustomTemplate(template.id, {
                          photo_layout: event.target.value as PhotoLayout,
                        })
                      }
                      className="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-sm disabled:bg-gray-100 disabled:text-gray-500"
                    >
                      <option value="auto">Auto</option>
                      <option value="two-column">Two column</option>
                      <option value="stacked">Stacked</option>
                    </select>
                  </label>
                  <label className="inline-flex items-center gap-2 text-xs text-gray-600 self-end">
                    <input
                      type="checkbox"
                      checked={Boolean(template.blank)}
                      disabled={!isCustom}
                      onChange={(event) =>
                        updateCustomTemplate(template.id, { blank: event.target.checked })
                      }
                    />
                    Blank page
                  </label>
                </div>
                <label className="text-xs text-gray-600 block mt-2">
                  Description
                  <input
                    type="text"
                    value={template.description ?? ""}
                    disabled={!isCustom}
                    onChange={(event) =>
                      updateCustomTemplate(template.id, {
                        description: event.target.value,
                      })
                    }
                    className="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-sm disabled:bg-gray-100 disabled:text-gray-500"
                  />
                </label>
                {isCustom ? (
                  <button
                    type="button"
                    onClick={() => {
                      void removeCustomTemplate(template.id);
                    }}
                    disabled={isSaving}
                    className="mt-2 inline-flex items-center gap-1 rounded-md border border-red-200 bg-red-50 px-2 py-1 text-xs font-semibold text-red-700 hover:bg-red-100 disabled:opacity-50 disabled:cursor-not-allowed"
                  >
                    <Trash2 className="h-3.5 w-3.5" />
                    Delete template
                  </button>
                ) : null}
              </div>
            );
          })}
        </div>
      </section>

      {status ? <p className="mt-4 text-sm text-gray-600">{status}</p> : null}

      <PageFooter note="Templates are stored per session and available when adding new pages." />
    </PageShell>
  );
}
