"use client";

import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useParams, useRouter } from "next/navigation";
import Link from "next/link";
import { api, Secret } from "@/lib/api";
import { Button, Card, CardHeader, CardTitle } from "@/components/ui";
import { Table, Thead, Tbody, Tr, Th, Td } from "@/components/ui";

const inputClass =
    "w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder-text-secondary/50 focus:border-accent focus:outline-none focus:ring-1 focus:ring-accent";


const STORE_NAME = "vantage-store";

function CopyBlock({ label, yaml }: { label: string; yaml: string }) {
    const [copied, setCopied] = useState(false);

    async function copy() {
        await navigator.clipboard.writeText(yaml);
        setCopied(true);
        setTimeout(() => setCopied(false), 2000);
    }

    return (
        <div>
            <div className="mb-1.5 flex items-center justify-between">
                <span className="text-sm font-medium text-text-secondary">{label}</span>
                <Button type="button" variant="ghost" size="sm" onClick={copy}>
                    {copied ? "Copied!" : "Copy"}
                </Button>
            </div>
            <pre className="overflow-x-auto rounded-lg border border-border bg-surface-2 p-3 font-mono text-xs leading-relaxed text-text-primary">{yaml}</pre>
        </div>
    );
}

function YamlModal({ group, onClose }: { group: string; onClose: () => void }) {
    const [namespace, setNamespace] = useState(group);
    const readUrl = typeof window !== "undefined" ? window.location.origin : "https://vantage.example.com";
    const ns = namespace.trim() || group;

    const externalSecret = `apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: ${group}
  namespace: ${ns}
spec:
  refreshInterval: 15m
  secretStoreRef:
    name: ${STORE_NAME}
    kind: ClusterSecretStore
  target:
    name: ${group}
    creationPolicy: Owner
  dataFrom:
    - extract:
        key: ${group}`;

    const clusterStore = `apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
  name: ${STORE_NAME}
spec:
  provider:
    webhook:
      url: "${readUrl}/api/secrets/{{ .remoteRef.key }}/values"
      method: GET
      result:
        jsonPath: "$"
      headers:
        Content-Type: "application/json"
        Authorization: "Bearer {{ .auth.token }}"
      secrets:
        - name: auth
          secretRef:
            name: vantage-eso-token
            namespace: external-secrets`;

    return (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4 backdrop-blur-sm">
            <div className="max-h-[90vh] w-full max-w-2xl overflow-y-auto rounded-xl border border-border bg-surface p-6">
                <h2 className="mb-1 text-lg font-semibold text-text-primary">
                    Kubernetes manifests for <span className="font-mono">{group}</span>
                </h2>
                <p className="mb-5 text-sm text-text-secondary">Apply the ExternalSecret in your app&apos;s namespace to sync this group into a Kubernetes Secret via ESO.</p>

                <div className="mb-5">
                    <label className="mb-1.5 block text-sm font-medium text-text-secondary">Namespace</label>
                    <input type="text" value={namespace} onChange={(e) => setNamespace(e.target.value)} placeholder={group} className={`${inputClass} font-mono`} />
                </div>

                <div className="space-y-5">
                    <CopyBlock label="ExternalSecret (apply per namespace)" yaml={externalSecret} />

                    <details className="group">
                        <summary className="cursor-pointer text-sm font-medium text-text-secondary hover:text-text-primary">One-time cluster setup: ClusterSecretStore</summary>
                        <p className="mb-3 mt-2 text-xs text-text-tertiary">
                            Apply this once per cluster. It requires a Secret named <span className="font-mono">vantage-eso-token</span> in the <span className="font-mono">external-secrets</span>{" "}
                            namespace holding the read token from Settings, labelled <span className="font-mono">external-secrets.io/type=webhook</span>.
                        </p>
                        <CopyBlock label="ClusterSecretStore" yaml={clusterStore} />
                    </details>
                </div>

                <div className="mt-6 flex justify-end">
                    <Button variant="ghost" onClick={onClose}>
                        Close
                    </Button>
                </div>
            </div>
        </div>
    );
}

function SecretRow({ group, secret }: { group: string; secret: Secret }) {
    const queryClient = useQueryClient();
    const [revealed, setRevealed] = useState<string | null>(null);
    const [copied, setCopied] = useState(false);

    const { mutate: reveal, isPending: revealing } = useMutation({
        mutationFn: () => api.revealSecret(group, secret.key),
        onSuccess: (res) => setRevealed(res.value),
    });

    const { mutate: remove, isPending: removing } = useMutation({
        mutationFn: () => api.deleteSecret(group, secret.key),
        onSuccess: () => queryClient.invalidateQueries({ queryKey: ["secret-group", group] }),
    });

    async function copy() {
        if (revealed == null) return;
        await navigator.clipboard.writeText(revealed);
        setCopied(true);
        setTimeout(() => setCopied(false), 2000);
    }

    return (
        <Tr>
            <Td label="Key">
                <span className="font-mono font-medium text-text-primary">{secret.key}</span>
            </Td>
            <Td label="Value">{revealed == null ? <span className="font-mono text-text-tertiary">••••••••••••</span> : <span className="font-mono text-xs break-all text-text-primary">{revealed}</span>}</Td>
            <Td label="Updated">
                <span className="text-text-secondary text-xs">{new Date(secret.updated_at).toLocaleString()}</span>
            </Td>
            <Td>
                <div className="flex justify-end gap-2">
                    {revealed == null ? (
                        <Button variant="ghost" size="sm" loading={revealing} onClick={() => reveal()}>
                            Reveal
                        </Button>
                    ) : (
                        <>
                            <Button variant="ghost" size="sm" onClick={copy}>
                                {copied ? "Copied!" : "Copy"}
                            </Button>
                            <Button variant="ghost" size="sm" onClick={() => setRevealed(null)}>
                                Hide
                            </Button>
                        </>
                    )}
                    <Button
                        variant="ghost"
                        size="sm"
                        loading={removing}
                        className="text-danger hover:text-danger"
                        onClick={() => {
                            if (confirm(`Delete key "${secret.key}"?`)) remove();
                        }}
                    >
                        Delete
                    </Button>
                </div>
            </Td>
        </Tr>
    );
}

function AddKeyCard({ group }: { group: string }) {
    const queryClient = useQueryClient();
    const [key, setKey] = useState("");
    const [value, setValue] = useState("");

    const {
        mutate: add,
        isPending,
        error,
    } = useMutation({
        mutationFn: () => api.putSecrets(group, { [key.trim()]: value }),
        onSuccess: () => {
            queryClient.invalidateQueries({ queryKey: ["secret-group", group] });
            setKey("");
            setValue("");
        },
    });

    return (
        <Card>
            <CardHeader>
                <CardTitle>Add / Update Key</CardTitle>
            </CardHeader>
            <p className="mb-4 text-sm text-text-secondary">Adding a key that already exists overwrites its value. Others are left untouched.</p>
            {error && <div className="mb-4 rounded-lg border border-danger/30 bg-danger/10 px-3 py-2 text-sm text-danger">{(error as Error).message}</div>}
            <div className="flex items-end gap-3">
                <div className="flex-1">
                    <label className="mb-1.5 block text-sm font-medium text-text-secondary">Key</label>
                    <input type="text" value={key} onChange={(e) => setKey(e.target.value)} placeholder="API_KEY" className={`${inputClass} font-mono`} />
                </div>
                <div className="flex-1">
                    <label className="mb-1.5 block text-sm font-medium text-text-secondary">Value</label>
                    <input type="text" value={value} onChange={(e) => setValue(e.target.value)} placeholder="myapikey456" className={`${inputClass} font-mono`} />
                </div>
                <Button variant="primary" loading={isPending} disabled={!key.trim() || !value} onClick={() => add()}>
                    Save
                </Button>
            </div>
        </Card>
    );
}

export default function SecretGroupPage() {
    const params = useParams();
    const router = useRouter();
    const queryClient = useQueryClient();
    const group = decodeURIComponent(String(params.group));
    const [showYaml, setShowYaml] = useState(false);

    const { data, isLoading, error } = useQuery({
        queryKey: ["secret-group", group],
        queryFn: () => api.getSecretGroup(group),
    });

    const { mutate: deleteGroup, isPending: deleting } = useMutation({
        mutationFn: () => api.deleteSecretGroup(group),
        onSuccess: () => {
            queryClient.invalidateQueries({ queryKey: ["secret-groups"] });
            router.push("/secrets");
        },
    });

    return (
        <div className="p-4 sm:p-6 lg:p-8">
            {showYaml && <YamlModal group={group} onClose={() => setShowYaml(false)} />}

            <Link href="/secrets" className="mb-4 inline-flex items-center gap-1 text-sm text-text-secondary hover:text-text-primary">
                ← Back to secrets
            </Link>

            <div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                <div className="min-w-0">
                    <h1 className="break-all font-mono text-2xl font-bold text-text-primary">{group}</h1>
                    <p className="mt-1 break-words text-sm text-text-secondary">
                        ESO reads this group at <span className="font-mono">GET /api/secrets/{group}/values</span>
                    </p>
                </div>
                <div className="flex flex-wrap items-center gap-3">
                    <Button variant="ghost" onClick={() => setShowYaml(true)}>
                        <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                            <path strokeLinecap="round" strokeLinejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5" />
                        </svg>
                        ExternalSecret YAML
                    </Button>
                    <Button
                        variant="ghost"
                        className="text-danger hover:text-danger"
                        loading={deleting}
                        onClick={() => {
                            if (confirm(`Delete the entire "${group}" group and all its keys?`)) deleteGroup();
                        }}
                    >
                        Delete Group
                    </Button>
                </div>
            </div>

            <div className="space-y-6">
                <AddKeyCard group={group} />

                <Card padding={false}>
                    {isLoading ? (
                        <div className="flex items-center justify-center py-20">
                            <div className="h-8 w-8 animate-spin rounded-full border-2 border-border border-t-accent" />
                        </div>
                    ) : error ? (
                        <div className="py-20 text-center text-danger">Failed to load group. It may have been deleted.</div>
                    ) : data && data.secrets.length > 0 ? (
                        <Table>
                            <Thead>
                                <Tr>
                                    <Th>Key</Th>
                                    <Th>Value</Th>
                                    <Th>Updated</Th>
                                    <Th />
                                </Tr>
                            </Thead>
                            <Tbody>
                                {data.secrets.map((s: Secret) => (
                                    <SecretRow key={s.key} group={group} secret={s} />
                                ))}
                            </Tbody>
                        </Table>
                    ) : (
                        <div className="py-16 text-center text-text-secondary">This group has no keys. Add one above.</div>
                    )}
                </Card>
            </div>
        </div>
    );
}
