import { useEffect, useMemo, useState } from "react";
import { Trash2 } from "lucide-react";
import {
  Button,
  ConfirmDialog,
  DataGrid,
  DismissibleAlert,
  FormField,
  ReferenceSelect,
  StatusBadge,
  TableActionGroup,
  type ApiSettings,
  type DataGridColumn
} from "@govoplan/core-webui";
import {
  createFileShare,
  fileShareTargetProvider,
  listFileShares,
  revokeFileShare,
  type FileShare,
  type ManagedFile
} from "../../../api/files";
import { FileDialog } from "./FileManagerComponents";
import { formatDate } from "../utils/fileManagerUtils";

type ShareTargetType = "user" | "group" | "tenant";
type SharePermission = "read" | "write" | "manage";

export default function FileShareDialog({
  settings,
  file,
  tenantId,
  onClose,
  onChanged
}: {
  settings: ApiSettings;
  file: ManagedFile;
  tenantId: string;
  onClose: () => void;
  onChanged: () => void;
}) {
  const [shares, setShares] = useState<FileShare[]>([]);
  const [targetType, setTargetType] = useState<ShareTargetType>("user");
  const [targetId, setTargetId] = useState("");
  const [permission, setPermission] = useState<SharePermission>("read");
  const [expiresAt, setExpiresAt] = useState("");
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const [revokeTarget, setRevokeTarget] = useState<FileShare | null>(null);
  const targetProvider = useMemo(
    () => targetType === "tenant"
      ? null
      : fileShareTargetProvider(settings, file.id, targetType),
    [file.id, settings, targetType]
  );

  useEffect(() => {
    void refresh();
  }, [file.id]);

  async function refresh() {
    setBusy(true);
    setError("");
    try {
      const response = await listFileShares(settings, file.id, {
        includeInactive: true
      });
      setShares(response.shares);
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setBusy(false);
    }
  }

  async function grant() {
    const effectiveTargetId = targetType === "tenant" ? tenantId : targetId;
    if (!effectiveTargetId) return;
    setBusy(true);
    setError("");
    try {
      await createFileShare(settings, file.id, {
        target_type: targetType,
        target_id: effectiveTargetId,
        permission,
        expires_at: expiresAt ? new Date(expiresAt).toISOString() : null
      });
      setTargetId("");
      setExpiresAt("");
      await refresh();
      onChanged();
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
      setBusy(false);
    }
  }

  async function revoke() {
    if (!revokeTarget) return;
    setBusy(true);
    setError("");
    try {
      await revokeFileShare(settings, file.id, revokeTarget.id);
      setRevokeTarget(null);
      await refresh();
      onChanged();
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
      setBusy(false);
    }
  }

  const columns = useMemo<DataGridColumn<FileShare>[]>(() => [
    {
      id: "target",
      header: "Target",
      minWidth: 220,
      resizable: true,
      sortable: true,
      filterable: true,
      value: (share) => `${share.target_type}: ${share.target_id}`
    },
    {
      id: "permission",
      header: "Permission",
      width: 115,
      sortable: true,
      filterable: true,
      value: (share) => share.permission
    },
    {
      id: "created",
      header: "Created",
      minWidth: 160,
      resizable: true,
      sortable: true,
      value: (share) => formatDate(share.created_at)
    },
    {
      id: "creator",
      header: "Created by",
      minWidth: 150,
      resizable: true,
      filterable: true,
      value: (share) => share.created_by_user_id || "System"
    },
    {
      id: "expiry",
      header: "Expires",
      minWidth: 160,
      resizable: true,
      sortable: true,
      value: (share) => share.expires_at ? formatDate(share.expires_at) : "No expiry"
    },
    {
      id: "status",
      header: "Status",
      width: 115,
      sortable: true,
      value: (share) => shareStatus(share),
      render: (share) => (
        <StatusBadge
          status={share.active ? "active" : "inactive"}
          label={shareStatus(share)}
        />
      )
    },
    {
      id: "actions",
      header: "Actions",
      width: 72,
      sticky: "end",
      align: "right",
      render: (share) => (
        <TableActionGroup
          minimumSlots={1}
          actions={[
            {
              id: "revoke",
              label: "Revoke share",
              icon: <Trash2 size={16} aria-hidden="true" />,
              variant: "danger",
              disabled: !share.active || busy,
              disabledReason: !share.active ? "This share is already inactive." : undefined,
              onClick: () => setRevokeTarget(share)
            }
          ]}
        />
      )
    }
  ], [busy]);

  return (
    <>
      <FileDialog title={`Manage shares - ${file.filename}`} onClose={() => !busy && onClose()}>
        <div className="file-share-dialog-content">
          {error ? (
            <DismissibleAlert tone="danger" resetKey={error}>
              {error}
            </DismissibleAlert>
          ) : null}
          <div className="file-share-form">
            <FormField label="Target type">
              <select
                value={targetType}
                disabled={busy}
                onChange={(event) => {
                  setTargetType(event.target.value as ShareTargetType);
                  setTargetId("");
                }}
              >
                <option value="user">User</option>
                <option value="group">Group</option>
                <option value="tenant">Entire tenant</option>
              </select>
            </FormField>
            <FormField label="Target">
              {targetType === "tenant" ? (
                <input value={tenantId} disabled readOnly />
              ) : targetProvider ? (
                <ReferenceSelect
                  value={targetId}
                  onChange={setTargetId}
                  provider={targetProvider}
                  disabled={busy}
                  placeholder={`Select a ${targetType}`}
                  aria-label={`Share target ${targetType}`}
                  required
                />
              ) : null}
            </FormField>
            <FormField label="Permission">
              <select
                value={permission}
                disabled={busy}
                onChange={(event) => setPermission(event.target.value as SharePermission)}
              >
                <option value="read">Read</option>
                <option value="write">Write</option>
                <option value="manage">Manage</option>
              </select>
            </FormField>
            <FormField label="Expires (optional)">
              <input
                type="datetime-local"
                value={expiresAt}
                min={minimumLocalDateTime()}
                disabled={busy}
                onChange={(event) => setExpiresAt(event.target.value)}
              />
            </FormField>
            <Button
              variant="primary"
              disabled={busy || (targetType !== "tenant" && !targetId)}
              onClick={() => void grant()}
            >
              Grant access
            </Button>
          </div>
          <DataGrid
            id={`file-${file.id}-shares`}
            rows={shares}
            columns={columns}
            getRowKey={(share) => share.id}
            emptyText={busy ? "Loading shares..." : "This file has no direct shares."}
            initialFit="container"
          />
          <div className="button-row compact-actions align-end">
            <Button onClick={onClose} disabled={busy}>Close</Button>
          </div>
        </div>
      </FileDialog>
      <ConfirmDialog
        open={Boolean(revokeTarget)}
        title="Revoke file share"
        message="Revoke this direct grant? Other independent grants remain in effect."
        confirmLabel="Revoke"
        cancelLabel="Cancel"
        tone="danger"
        busy={busy}
        onConfirm={() => void revoke()}
        onCancel={() => setRevokeTarget(null)}
      />
    </>
  );
}

function shareStatus(share: FileShare): string {
  if (share.revoked_at) return "Revoked";
  if (share.expires_at && new Date(share.expires_at).getTime() <= Date.now()) {
    return "Expired";
  }
  return "Active";
}

function minimumLocalDateTime(): string {
  const now = new Date(Date.now() + 60_000);
  const local = new Date(now.getTime() - now.getTimezoneOffset() * 60_000);
  return local.toISOString().slice(0, 16);
}
