import { useRef, useState } from "react";
import type { RegexProjectV1 } from "../project/project.types";
import {
  importProjectDocument,
  projectFileName,
  serializeProject,
} from "../project/project.serialization";
import { MAXIMUM_PROJECT_DOCUMENT_BYTES } from "../project/project-limits";

function downloadProject(project: RegexProjectV1, serialized: string): void {
  const url = URL.createObjectURL(
    new Blob([serialized], { type: "application/json" }),
  );
  const anchor = document.createElement("a");
  anchor.href = url;
  anchor.download = projectFileName(project);
  anchor.click();
  window.setTimeout(() => URL.revokeObjectURL(url), 1_000);
}

export function ProjectPanel({
  project,
  open,
  onClose,
  onImport,
  onSaveLocal,
  onLoadLocal,
}: {
  readonly project: RegexProjectV1;
  readonly open: boolean;
  readonly onClose: () => void;
  readonly onImport: (project: RegexProjectV1) => void;
  readonly onSaveLocal: (
    includeText: boolean,
    includeUnitTestSubjects: boolean,
  ) => Promise<void>;
  readonly onLoadLocal: () => Promise<void>;
}) {
  const input = useRef<HTMLInputElement>(null);
  const [includeText, setIncludeText] = useState(false);
  const [includeTestSubjects, setIncludeTestSubjects] = useState(false);
  const [includeLocalTestSubjects, setIncludeLocalTestSubjects] =
    useState(false);
  const [status, setStatus] = useState("");
  if (!open) return null;
  return (
    <section
      className="project-popover panel"
      aria-labelledby="project-heading"
    >
      <header className="panel-heading">
        <div>
          <p className="eyebrow">Versioned local project</p>
          <h2 id="project-heading">Project</h2>
        </div>
        <button
          type="button"
          className="icon-button"
          aria-label="Close project panel"
          onClick={onClose}
        >
          ×
        </button>
      </header>
      <p>
        <strong>{project.name}</strong> · schema {project.schemaVersion}
      </p>
      <p className="field-help">
        Corpus documents, applied outputs and corpus results are always excluded
        from project JSON and local saves.
      </p>
      <label className="check-control">
        <input
          type="checkbox"
          checked={includeText}
          onChange={(event) => setIncludeText(event.target.checked)}
        />
        Include interactive test text
      </label>
      <label className="check-control">
        <input
          type="checkbox"
          checked={includeTestSubjects}
          onChange={(event) => setIncludeTestSubjects(event.target.checked)}
        />
        Include unit-test subjects in export
      </label>
      <label className="check-control">
        <input
          type="checkbox"
          checked={includeLocalTestSubjects}
          onChange={(event) =>
            setIncludeLocalTestSubjects(event.target.checked)
          }
        />
        Include unit-test subjects in local save
      </label>
      {includeText || includeTestSubjects || includeLocalTestSubjects ? (
        <p className="privacy-warning">
          Included subject text may contain sensitive data. The file remains
          local unless you share it.
        </p>
      ) : null}
      <div className="project-actions">
        <button
          type="button"
          className="primary-button"
          onClick={() => {
            try {
              const serialized = serializeProject(project, {
                includeTestText: includeText,
                includeUnitTestSubjects: includeTestSubjects,
              });
              downloadProject(project, serialized);
              setStatus("Exported project JSON.");
            } catch (error: unknown) {
              setStatus(error instanceof Error ? error.message : String(error));
            }
          }}
        >
          Export JSON
        </button>
        <button
          type="button"
          className="secondary-button"
          onClick={() => input.current?.click()}
        >
          Import JSON
        </button>
        <button
          type="button"
          className="secondary-button"
          onClick={() => {
            void onSaveLocal(includeText, includeLocalTestSubjects)
              .then(() => setStatus("Saved locally."))
              .catch((error: unknown) =>
                setStatus(
                  error instanceof Error ? error.message : String(error),
                ),
              );
          }}
        >
          Save locally
        </button>
        <button
          type="button"
          className="secondary-button"
          onClick={() => {
            void onLoadLocal()
              .then(() =>
                setStatus("Loaded locally; live execution is paused."),
              )
              .catch((error: unknown) =>
                setStatus(
                  error instanceof Error ? error.message : String(error),
                ),
              );
          }}
        >
          Load local save
        </button>
      </div>
      <input
        ref={input}
        type="file"
        accept="application/json,.json"
        className="visually-hidden"
        tabIndex={-1}
        aria-label="Import regex project JSON file"
        onChange={(event) => {
          const file = event.target.files?.[0];
          if (!file) return;
          if (file.size > MAXIMUM_PROJECT_DOCUMENT_BYTES) {
            setStatus("Project document exceeds the 32 MiB import limit.");
            event.target.value = "";
            return;
          }
          void file
            .text()
            .then(importProjectDocument)
            .then((imported) => {
              onImport(imported);
              setStatus("Imported and validated; live execution is paused.");
            })
            .catch((error: unknown) =>
              setStatus(error instanceof Error ? error.message : String(error)),
            );
          event.target.value = "";
        }}
      />
      <p role="status" className="project-status">
        {status}
      </p>
    </section>
  );
}
