import { useState } from "react";
import { open, save } from "@tauri-apps/plugin-dialog";
import type { ArchiveJobResult } from "../lib/types";

interface ArchivePanelProps {
  onExtract: (source: string, destination: string) => Promise<ArchiveJobResult>;
  onCompress: (source: string, destination: string) => Promise<ArchiveJobResult>;
}

type ArchiveAction = "extract" | "compress" | null;

export function ArchivePanel({ onExtract, onCompress }: ArchivePanelProps) {
  const [source, setSource] = useState("");
  const [destination, setDestination] = useState("");
  const [lastResult, setLastResult] = useState<ArchiveJobResult | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [pendingAction, setPendingAction] = useState<ArchiveAction>(null);

  async function runAction(action: Exclude<ArchiveAction, null>) {
    if (!source || !destination) {
      setError("Choose both a source and destination before running an archive job.");
      return;
    }

    setPendingAction(action);
    setError(null);
    try {
      const result = action === "extract" ? await onExtract(source, destination) : await onCompress(source, destination);
      setLastResult(result);
    } catch (cause) {
      setError(cause instanceof Error ? cause.message : "Archive job failed.");
    } finally {
      setPendingAction(null);
    }
  }

  return (
    <div className="glass rounded-[32px] p-6">
      <div className="text-xs uppercase tracking-[0.2em] text-textMuted">Archive utilities</div>
      <h2 className="mt-2 text-2xl font-semibold text-white">Extract and package sample crates</h2>
      <p className="mt-3 max-w-2xl text-sm text-textMuted">
        Supports <span className="text-text">ZIP</span>, <span className="text-text">TAR</span>, and{" "}
        <span className="text-text">TAR.GZ / TGZ</span>. Extraction expects an archive file and a target
        folder. Compression accepts either a file or directory and writes a new archive.
      </p>

      <div className="mt-6 grid gap-4">
        <div className="rounded-3xl border border-line/35 bg-white/5 p-4">
          <div className="text-xs uppercase tracking-[0.2em] text-textMuted">Source</div>
          <div className="mt-3 flex gap-3">
            <input
              value={source}
              onChange={(event) => setSource(event.target.value)}
              className="flex-1 rounded-2xl border border-line/40 bg-panel/70 px-4 py-3 text-text outline-none"
              placeholder="Archive file to extract, or file/folder to compress"
            />
            <button
              type="button"
              className="rounded-2xl border border-line/45 px-4 py-3 text-text"
              onClick={async () => {
                const picked = await open({
                  directory: false,
                  multiple: false,
                  filters: [{ name: "Archives", extensions: ["zip", "tar", "gz", "tgz"] }],
                });
                if (typeof picked === "string") setSource(picked);
              }}
            >
              File
            </button>
            <button
              type="button"
              className="rounded-2xl border border-line/45 px-4 py-3 text-text"
              onClick={async () => {
                const picked = await open({ directory: true, multiple: false });
                if (typeof picked === "string") setSource(picked);
              }}
            >
              Folder
            </button>
          </div>
        </div>

        <div className="rounded-3xl border border-line/35 bg-white/5 p-4">
          <div className="text-xs uppercase tracking-[0.2em] text-textMuted">Destination</div>
          <div className="mt-3 flex gap-3">
            <input
              value={destination}
              onChange={(event) => setDestination(event.target.value)}
              className="flex-1 rounded-2xl border border-line/40 bg-panel/70 px-4 py-3 text-text outline-none"
              placeholder="Target folder for extract, or archive path like crate.tar.gz"
            />
            <button
              type="button"
              className="rounded-2xl border border-line/45 px-4 py-3 text-text"
              onClick={async () => {
                const picked = await open({ directory: true, multiple: false });
                if (typeof picked === "string") setDestination(picked);
              }}
            >
              Folder
            </button>
            <button
              type="button"
              className="rounded-2xl border border-line/45 px-4 py-3 text-text"
              onClick={async () => {
                const picked = await save({
                  filters: [
                    { name: "ZIP", extensions: ["zip"] },
                    { name: "TAR", extensions: ["tar"] },
                    { name: "TAR.GZ", extensions: ["tar.gz", "tgz"] },
                  ],
                });
                if (typeof picked === "string") setDestination(picked);
              }}
            >
              Save as
            </button>
          </div>
        </div>
      </div>

      <div className="mt-5 flex gap-3">
        <button
          type="button"
          onClick={() => void runAction("extract")}
          disabled={pendingAction !== null}
          className="rounded-2xl bg-accent px-5 py-3 font-semibold text-black disabled:cursor-not-allowed disabled:opacity-50"
        >
          {pendingAction === "extract" ? "Extracting..." : "Extract"}
        </button>
        <button
          type="button"
          onClick={() => void runAction("compress")}
          disabled={pendingAction !== null}
          className="rounded-2xl border border-line/45 px-5 py-3 text-text disabled:cursor-not-allowed disabled:opacity-50"
        >
          {pendingAction === "compress" ? "Compressing..." : "Create archive"}
        </button>
      </div>

      {error ? (
        <div className="mt-5 rounded-2xl border border-red-400/35 bg-red-500/10 p-4 text-sm text-red-100">
          {error}
        </div>
      ) : null}

      {lastResult ? (
        <div className="mt-5 rounded-2xl border border-line/35 bg-white/5 p-4 text-sm text-text">
          Output: {lastResult.output_path}
          <div className="mt-2 text-textMuted">{lastResult.processed_entries} items processed</div>
        </div>
      ) : null}
    </div>
  );
}
