import { useEffect, useState } from "react";
import { apiFetch, createEventSourceFor } from "./api";
import { downloadFile } from "./export";
import { downloadExport } from "./exportHistory";
import { useTranslation } from "react-i18next";

type Tenant = {
  id: string;
  name: string;
  isActive: boolean;
  _count?: { users: number; mailboxAccounts: number; jobs: number };
};

type User = {
  id: string;
  email: string;
  role: string;
  isActive: boolean;
  tenant?: { id: string; name: string } | null;
};

type Account = {
  id: string;
  email: string;
  provider: string;
  isActive: boolean;
  tenant?: { id: string; name: string } | null;
};

type Job = {
  id: string;
  status: string;
  createdAt: string;
  tenant?: { id: string; name: string } | null;
  mailboxAccount?: { id: string; email: string } | null;
};

type Props = {
  token: string;
  onImpersonate: (token: string) => void;
};

export default function AdminPanel({ token, onImpersonate }: Props) {
  const { t } = useTranslation();
  const [tenants, setTenants] = useState<Tenant[]>([]);
  const [users, setUsers] = useState<User[]>([]);
  const [accounts, setAccounts] = useState<Account[]>([]);
  const [jobs, setJobs] = useState<Job[]>([]);
  const [activeTab, setActiveTab] = useState<"tenants" | "users" | "accounts" | "jobs">("tenants");
  const [resetUserId, setResetUserId] = useState<string | null>(null);
  const [resetPassword, setResetPassword] = useState("");
  const [exportTenantId, setExportTenantId] = useState<string | null>(null);
  const [exportStatus, setExportStatus] = useState<"idle" | "loading" | "done" | "failed">("idle");
  const [exportJobId, setExportJobId] = useState<string | null>(null);
  const [exportHistory, setExportHistory] = useState<{ id: string; status: string; expiresAt?: string | null; createdAt?: string }[]>([]);
  const [exportScope, setExportScope] = useState<"all" | "users" | "accounts" | "jobs" | "rules">("all");
  const [exportFormat, setExportFormat] = useState<"json" | "csv" | "zip">("json");
  const [tenantSort, setTenantSort] = useState<"recent" | "oldest" | "name">("recent");
  const [userSort, setUserSort] = useState<"recent" | "oldest" | "email">("recent");
  const [accountSort, setAccountSort] = useState<"recent" | "oldest" | "email">("recent");
  const [jobSort, setJobSort] = useState<"recent" | "oldest" | "status">("recent");

  const loadAll = async () => {
    const tenantData = await apiFetch("/admin/tenants", {}, token);
    setTenants(tenantData.tenants ?? []);

    const usersData = await apiFetch("/admin/users", {}, token);
    setUsers(usersData.users ?? []);

    const accountsData = await apiFetch("/admin/accounts", {}, token);
    setAccounts(accountsData.accounts ?? []);

    const jobsData = await apiFetch("/admin/jobs", {}, token);
    setJobs(jobsData.jobs ?? []);
    const exportsData = await apiFetch("/admin/exports", {}, token);
    setExportHistory(exportsData.exports ?? []);
  };

  useEffect(() => {
    loadAll().catch(() => undefined);
  }, []);

  const toggleTenant = async (tenant: Tenant) => {
    const result = await apiFetch(
      `/admin/tenants/${tenant.id}`,
      { method: "PUT", body: JSON.stringify({ isActive: !tenant.isActive }) },
      token
    );
    setTenants((prev) => prev.map((item) => (item.id === tenant.id ? result.tenant : item)));
  };

  const exportTenant = async (tenant: Tenant) => {
    setExportTenantId(tenant.id);
    setExportStatus("loading");
    if (exportFormat === "json") {
      const result = await apiFetch(`/admin/tenants/${tenant.id}/export?scope=${exportScope}`, {}, token);
      const blob = new Blob([JSON.stringify(result, null, 2)], { type: "application/json" });
      downloadFile(blob, `tenant-${tenant.id}.json`);
    } else if (exportFormat === "csv") {
      await exportTenantCsv(tenant);
      return;
    } else {
      const result = await apiFetch(`/admin/tenants/${tenant.id}/export?format=zip&scope=${exportScope}`, {}, token);
      setExportJobId(result.jobId);
      setExportHistory((prev) => [{ id: result.jobId, status: "QUEUED" }, ...prev]);
      const source = createEventSourceFor(`exports/${result.jobId}`, token);
      source.onmessage = async (event) => {
        const data = JSON.parse(event.data);
        setExportHistory((prev) =>
          prev.map((item) => (item.id === data.id ? { ...item, status: data.status, expiresAt: data.expiresAt } : item))
        );
        if (data.status === "DONE") {
          const response = await downloadExport(token, result.jobId);
          const blob = await response.blob();
          downloadFile(blob, `tenant-${tenant.id}.zip`);
          setExportStatus("done");
          source.close();
          setTimeout(() => setExportStatus("idle"), 1500);
        } else if (data.status === "FAILED") {
          setExportStatus("failed");
          source.close();
        }
      };
      return;
    }
    setExportStatus("done");
    setTimeout(() => setExportStatus("idle"), 1500);
  };

  const exportTenantCsv = async (tenant: Tenant) => {
    setExportTenantId(tenant.id);
    setExportStatus("loading");
    const base = import.meta.env.VITE_API_URL ?? "http://localhost:8000";
    const response = await fetch(`${base}/admin/tenants/${tenant.id}/export?format=csv&scope=${exportScope}`, {
      headers: { Authorization: `Bearer ${token}` }
    });
    const text = await response.text();
    const blob = new Blob([text], { type: "text/csv" });
    downloadFile(blob, `tenant-${tenant.id}.csv`);
    setExportStatus("done");
    setTimeout(() => setExportStatus("idle"), 1500);
  };

  const deleteTenant = async (tenant: Tenant) => {
    if (!confirm(t("adminDeleteConfirm", { name: tenant.name }))) return;
    await apiFetch(`/admin/tenants/${tenant.id}`, { method: "DELETE" }, token);
    setTenants((prev) => prev.filter((item) => item.id !== tenant.id));
  };

  const toggleUser = async (user: User) => {
    const result = await apiFetch(
      `/admin/users/${user.id}`,
      { method: "PUT", body: JSON.stringify({ isActive: !user.isActive }) },
      token
    );
    setUsers((prev) => prev.map((item) => (item.id === user.id ? result.user : item)));
  };

  const toggleAccount = async (account: Account) => {
    const result = await apiFetch(
      `/admin/accounts/${account.id}`,
      { method: "PUT", body: JSON.stringify({ isActive: !account.isActive }) },
      token
    );
    setAccounts((prev) => prev.map((item) => (item.id === account.id ? result.account : item)));
  };

  const setRole = async (user: User, role: "USER" | "ADMIN") => {
    const result = await apiFetch(
      `/admin/users/${user.id}/role`,
      { method: "PUT", body: JSON.stringify({ role }) },
      token
    );
    setUsers((prev) => prev.map((item) => (item.id === user.id ? result.user : item)));
  };

  const impersonate = async (user: User) => {
    const result = await apiFetch(`/admin/impersonate/${user.id}`, { method: "POST" }, token);
    onImpersonate(result.token);
  };

  const resetPasswordForUser = async () => {
    if (!resetUserId || resetPassword.length < 10) return;
    await apiFetch(`/admin/users/${resetUserId}/reset`, {
      method: "POST",
      body: JSON.stringify({ password: resetPassword })
    }, token);
    setResetUserId(null);
    setResetPassword("");
  };

  const cancelJob = async (job: Job) => {
    await apiFetch(`/admin/jobs/${job.id}/cancel`, { method: "POST" }, token);
    setJobs((prev) => prev.map((item) => (item.id === job.id ? { ...item, status: "CANCELED" } : item)));
  };

  const retryJob = async (job: Job) => {
    await apiFetch(`/admin/jobs/${job.id}/retry`, { method: "POST" }, token);
    loadAll().catch(() => undefined);
  };

  const sortBy = <T,>(items: T[], mode: string, getKey: (item: T) => string) => {
    const sorted = [...items];
    if (mode === "name" || mode === "email" || mode === "status") {
      sorted.sort((a, b) => getKey(a).localeCompare(getKey(b)));
    } else if (mode === "oldest") {
      sorted.reverse();
    }
    return sorted;
  };

  const tenantsSorted = sortBy(tenants, tenantSort, (t) => t.name);
  const usersSorted = sortBy(users, userSort, (u) => u.email);
  const accountsSorted = sortBy(accounts, accountSort, (a) => a.email);
  const jobsSorted = sortBy(jobs, jobSort, (j) => j.status);
  const mapJobStatus = (status: string) => {
    switch (status) {
      case "RUNNING":
        return t("statusRunning");
      case "QUEUED":
        return t("statusQueued");
      case "SUCCEEDED":
        return t("statusSucceeded");
      case "FAILED":
        return t("statusFailed");
      case "CANCELED":
        return t("statusCanceled");
      default:
        return status;
    }
  };

  return (
    <section className="admin-panel">
      <div className="admin-tabs">
        {(["tenants", "users", "accounts", "jobs"] as const).map((tab) => (
          <button
            key={tab}
            className={activeTab === tab ? "active" : ""}
            onClick={() => setActiveTab(tab)}
          >
            {t(`admin${tab.charAt(0).toUpperCase()}${tab.slice(1)}`)}
          </button>
        ))}
      </div>

      {activeTab === "tenants" && (
        <div className="card">
          <h3>{t("adminTenants")}</h3>
          <div className="filter-row">
            <label>
              {t("adminSortLabel")}
              <select value={tenantSort} onChange={(event) => setTenantSort(event.target.value as typeof tenantSort)}>
                <option value="recent">{t("adminSortRecent")}</option>
                <option value="oldest">{t("adminSortOldest")}</option>
                <option value="name">{t("adminSortName")}</option>
              </select>
            </label>
          </div>
          <div className="export-panel">
            <h4>{t("adminTenantExport")}</h4>
            <p className="status-note">{t("adminExportHint")}</p>
            <label className="toggle">
              <span>{t("adminExportScope")}</span>
              <select value={exportScope} onChange={(event) => setExportScope(event.target.value as typeof exportScope)}>
                <option value="all">{t("adminExportAll")}</option>
                <option value="users">{t("adminExportUsers")}</option>
                <option value="accounts">{t("adminExportAccounts")}</option>
                <option value="jobs">{t("adminExportJobs")}</option>
                <option value="rules">{t("adminExportRules")}</option>
              </select>
            </label>
            <label className="toggle">
              <span>{t("adminExportFormat")}</span>
              <select value={exportFormat} onChange={(event) => setExportFormat(event.target.value as typeof exportFormat)}>
                <option value="json">{t("exportFormatJson")}</option>
                <option value="csv">{t("exportFormatCsv")}</option>
                <option value="zip">{t("exportFormatZip")}</option>
              </select>
            </label>
          </div>
          {tenantsSorted.map((tenant) => (
            <div key={tenant.id} className="list-item">
              <div>
                <div className="badge">
                  <strong>{tenant.name}</strong>
                  <span className={`status-badge ${tenant.isActive ? "" : "missing"}`}>
                    {tenant.isActive ? t("adminActive") : t("adminInactive")}
                  </span>
                </div>
                <p>
                  {t("countUsers", { count: tenant._count?.users ?? 0 })} ·{" "}
                  {t("countAccounts", { count: tenant._count?.mailboxAccounts ?? 0 })} ·{" "}
                  {t("countJobs", { count: tenant._count?.jobs ?? 0 })}
                </p>
              </div>
              <div className="inline-actions">
                <button className="ghost" onClick={() => exportTenant(tenant)}>{t("adminExportStart")}</button>
                <button className="ghost" onClick={() => toggleTenant(tenant)}>
                  {tenant.isActive ? t("adminDisable") : t("adminEnable")}
                </button>
                <button className="ghost" onClick={() => deleteTenant(tenant)}>{t("adminDelete")}</button>
              </div>
            </div>
          ))}
          {exportTenantId && (
            <p className="status-note">
              {exportStatus === "loading"
                ? t("adminExporting")
                : exportStatus === "done"
                  ? t("adminExportDone")
                  : exportStatus === "failed"
                    ? t("adminExportFailed")
                    : ""}
            </p>
          )}
          {exportHistory.length > 0 && (
            <div className="export-history">
              <h4>{t("exportHistory")}</h4>
              {exportHistory.map((item) => (
                <div key={item.id} className="list-item">
                  <div>
                    <strong>{item.id.slice(0, 6)}</strong>
                    <p>
                      {item.expiresAt && new Date(item.expiresAt) < new Date()
                        ? t("exportStatusExpired")
                        : item.status === "QUEUED"
                          ? t("exportStatusQueued")
                          : item.status === "RUNNING"
                            ? t("exportStatusRunning")
                            : item.status === "DONE"
                              ? t("exportStatusDone")
                              : t("exportStatusFailed")}
                    </p>
                  </div>
                  <div className="inline-actions">
                    <span>
                      {item.createdAt ? new Date(item.createdAt).toLocaleString() : "-"} ·{" "}
                      {t("exportExpires")}: {item.expiresAt ? new Date(item.expiresAt).toLocaleString() : "-"}
                    </span>
                    <button
                      className="ghost"
                      disabled={item.status !== "DONE" || (item.expiresAt ? new Date(item.expiresAt) < new Date() : false)}
                      onClick={async () => {
                        const response = await downloadExport(token, item.id);
                        if (response.ok) {
                          const blob = await response.blob();
                          downloadFile(blob, `export-${item.id}.zip`);
                        }
                      }}
                    >
                      {t("exportDownload")}
                    </button>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {activeTab === "users" && (
        <div className="card">
          <h3>{t("adminUsers")}</h3>
          <div className="filter-row">
            <label>
              {t("adminSortLabel")}
              <select value={userSort} onChange={(event) => setUserSort(event.target.value as typeof userSort)}>
                <option value="recent">{t("adminSortRecent")}</option>
                <option value="oldest">{t("adminSortOldest")}</option>
                <option value="email">{t("adminSortEmail")}</option>
              </select>
            </label>
          </div>
          {usersSorted.map((user) => (
            <div key={user.id} className="list-item">
              <div>
                <div className="badge">
                  <strong>{user.email}</strong>
                  <span className={`status-badge ${user.isActive ? "" : "missing"}`}>
                    {user.isActive ? t("adminActive") : t("adminInactive")}
                  </span>
                </div>
                <p>{user.role} · {user.tenant?.name ?? "-"}</p>
              </div>
              <div className="inline-actions">
                <button className="ghost" onClick={() => setRole(user, user.role === "ADMIN" ? "USER" : "ADMIN")}>
                  {user.role === "ADMIN" ? t("adminMakeUser") : t("adminMakeAdmin")}
                </button>
                <button className="ghost" onClick={() => toggleUser(user)}>
                  {user.isActive ? t("adminDisable") : t("adminEnable")}
                </button>
                <button className="ghost" onClick={() => impersonate(user)}>
                  {t("adminImpersonate")}
                </button>
                <button className="ghost" onClick={() => setResetUserId(user.id)}>
                  {t("adminResetPassword")}
                </button>
              </div>
            </div>
          ))}
          {resetUserId && (
            <div className="admin-modal">
              <div className="modal-content">
                <h4>{t("adminResetTitle")}</h4>
                <input
                  placeholder={t("adminResetPlaceholder")}
                  type="password"
                  value={resetPassword}
                  onChange={(event) => setResetPassword(event.target.value)}
                />
                <div className="inline-actions">
                  <button className="ghost" onClick={() => setResetUserId(null)}>{t("adminCancel")}</button>
                  <button className="primary" onClick={resetPasswordForUser}>{t("adminConfirmReset")}</button>
                </div>
              </div>
            </div>
          )}
        </div>
      )}

      {activeTab === "accounts" && (
        <div className="card">
          <h3>{t("adminAccounts")}</h3>
          <div className="filter-row">
            <label>
              {t("adminSortLabel")}
              <select value={accountSort} onChange={(event) => setAccountSort(event.target.value as typeof accountSort)}>
                <option value="recent">{t("adminSortRecent")}</option>
                <option value="oldest">{t("adminSortOldest")}</option>
                <option value="email">{t("adminSortEmail")}</option>
              </select>
            </label>
          </div>
          {accountsSorted.map((account) => (
            <div key={account.id} className="list-item">
              <div>
                <div className="badge">
                  <strong>{account.email}</strong>
                  <span className={`status-badge ${account.isActive ? "" : "missing"}`}>
                    {account.isActive ? t("adminActive") : t("adminInactive")}
                  </span>
                </div>
                <p>{account.provider} · {account.tenant?.name ?? "-"}</p>
              </div>
              <button className="ghost" onClick={() => toggleAccount(account)}>
                {account.isActive ? t("adminDisable") : t("adminEnable")}
              </button>
            </div>
          ))}
        </div>
      )}

      {activeTab === "jobs" && (
        <div className="card">
          <h3>{t("adminJobs")}</h3>
          <div className="filter-row">
            <label>
              {t("adminSortLabel")}
              <select value={jobSort} onChange={(event) => setJobSort(event.target.value as typeof jobSort)}>
                <option value="recent">{t("adminSortRecent")}</option>
                <option value="oldest">{t("adminSortOldest")}</option>
                <option value="status">{t("adminSortStatus")}</option>
              </select>
            </label>
          </div>
          {jobsSorted.map((job) => (
            <div key={job.id} className="list-item">
              <div>
                <strong>{mapJobStatus(job.status)}</strong>
                <p>{job.tenant?.name ?? "-"} · {job.mailboxAccount?.email ?? "-"}</p>
              </div>
              <div className="inline-actions">
                <button className="ghost" onClick={() => retryJob(job)}>{t("adminRetry")}</button>
                <button className="ghost" onClick={() => cancelJob(job)}>{t("adminCancelJob")}</button>
                <span>{new Date(job.createdAt).toLocaleString()}</span>
              </div>
            </div>
          ))}
        </div>
      )}
    </section>
  );
}
