import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { api, formatUsd } from "../services/api";
import { toast } from "react-toastify";
import { ConfirmDialog } from "../components/ConfirmDialog";
import { usePageTitle } from "../hooks/usePageTitle";
import { RefreshCw, Link2, Search, X, Lock, Settings } from "lucide-react";

interface Repo {
  owner: string;
  name: string;
  fullName: string;
  htmlUrl: string;
  isPrivate: boolean;
  isEnabled: boolean;
  claimedByOther: boolean;
  config: any;
  costUsd: number;
}

type VisibilityFilter = "all" | "public" | "private";
type StatusFilter = "all" | "enabled" | "disabled";

export function Repos() {
  const navigate = useNavigate();
  usePageTitle("Repositories");
  const [repos, setRepos] = useState<Repo[]>([]);
  const [loading, setLoading] = useState(true);
  const [disableConfirm, setDisableConfirm] = useState<{ owner: string; repo: string } | null>(null);
  const [togglingRepo, setTogglingRepo] = useState<string | null>(null);
  const [search, setSearch] = useState("");
  const [debouncedSearch, setDebouncedSearch] = useState("");
  const [visibility, setVisibility] = useState<VisibilityFilter>("all");
  const [status, setStatus] = useState<StatusFilter>("all");

  useEffect(() => {
    const t = setTimeout(() => setDebouncedSearch(search), 250);
    return () => clearTimeout(t);
  }, [search]);

  const load = async () => {
    setLoading(true);
    const res = await api.repos.list();
    if (res.ok) {
      setRepos((res.data || []) as Repo[]);
    } else {
      toast.error(res.message || "Failed to load repos");
    }
    setLoading(false);
  };

  useEffect(() => { load(); }, []);

  const handleToggle = async (repo: Repo) => {
    const key = `${repo.owner}/${repo.name}`;
    if (repo.isEnabled) {
      setDisableConfirm({ owner: repo.owner, repo: repo.name });
      return;
    }
    setTogglingRepo(key);
    const res = await api.repos.toggle(repo.owner, repo.name, true);
    setTogglingRepo(null);
    if (res.ok) { toast.success("Repo enabled"); load(); }
    else toast.error(res.message || "Failed to enable repo");
  };

  const handleDisable = async () => {
    if (!disableConfirm) return;
    const key = `${disableConfirm.owner}/${disableConfirm.repo}`;
    setDisableConfirm(null);
    setTogglingRepo(key);
    const res = await api.repos.toggle(disableConfirm.owner, disableConfirm.repo, false);
    setTogglingRepo(null);
    if (res.ok) { toast.success("Repo disabled"); load(); }
    else toast.error(res.message || "Failed to disable repo");
  };

  if (loading) {
    return <div className="space-y-3">
      {[...Array(4)].map((_, i) => <div key={i} className="h-16 bg-gray-100 dark:bg-slate-800 rounded-xl animate-pulse" />)}
    </div>;
  }

  const query = debouncedSearch.trim().toLowerCase();
  const filteredRepos = repos.filter(repo => {
    if (query && !repo.fullName.toLowerCase().includes(query)) return false;
    if (visibility === "public" && repo.isPrivate) return false;
    if (visibility === "private" && !repo.isPrivate) return false;
    if (status === "enabled" && !repo.isEnabled) return false;
    if (status === "disabled" && repo.isEnabled) return false;
    return true;
  });
  const groupedSections = [
    { label: "Configured", repos: groupReposByOwner(filteredRepos.filter(repo => repo.config)) },
    { label: "Other repos", repos: groupReposByOwner(filteredRepos.filter(repo => !repo.config)) },
  ].filter(section => section.repos.length > 0);

  return (
    <div className="max-w-3xl space-y-4">
      <ConfirmDialog
        open={!!disableConfirm}
        title="Disable Repo"
        message={`Disabling "${disableConfirm?.owner}/${disableConfirm?.repo}" will delete the Gitea webhook. PR preview events will no longer be received.`}
        confirmLabel="Disable & Delete Webhook"
        onConfirm={handleDisable}
        onCancel={() => setDisableConfirm(null)}
        danger
      />

      <div className="flex items-center justify-between">
        <h1 className="text-2xl font-bold">Repo Configuration</h1>
        <button onClick={load} className="inline-flex items-center gap-1 text-sm text-blue-600 dark:text-blue-400 hover:underline"><RefreshCw size={14} /> Refresh</button>
      </div>

      {repos.length === 0 && (
        <div className="text-center py-16">
          <Link2 size={48} className="mx-auto mb-4 text-gray-400 dark:text-slate-500" />
          <h2 className="text-lg font-semibold mb-2">No repos found</h2>
          <p className="text-gray-500 dark:text-slate-400">Configure your Gitea credentials in Settings first.</p>
        </div>
      )}

      {repos.length > 0 && (
        <div className="flex flex-col sm:flex-row gap-2">
          <div className="relative flex-1">
            <Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
            <input
              type="text"
              value={search}
              onChange={e => setSearch(e.target.value)}
              placeholder="Search repos..."
              className={`${inputCls} pl-9`}
            />
            {search && (
              <button
                onClick={() => setSearch("")}
                className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-slate-200"
                title="Clear search"
              ><X size={16} /></button>
            )}
          </div>
          <select value={visibility} onChange={e => setVisibility(e.target.value as VisibilityFilter)} className={`${inputCls} sm:w-40`}>
            <option value="all">All visibility</option>
            <option value="public">Public only</option>
            <option value="private">Private only</option>
          </select>
          <select value={status} onChange={e => setStatus(e.target.value as StatusFilter)} className={`${inputCls} sm:w-40`}>
            <option value="all">All status</option>
            <option value="enabled">Enabled only</option>
            <option value="disabled">Disabled only</option>
          </select>
        </div>
      )}

      {repos.length > 0 && filteredRepos.length === 0 && (
        <div className="text-center py-12 text-gray-500 dark:text-slate-400">
          No repos match your search or filters.
        </div>
      )}

      {groupedSections.map(section => (
        <section key={section.label} className="space-y-3">
          <div className="flex items-center gap-2 pt-2">
            <h2 className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-slate-400">{section.label}</h2>
            <div className="h-px flex-1 bg-gray-200 dark:bg-slate-700" />
          </div>

          {section.repos.map(group => (
            <div key={`${section.label}-${group.owner}`} className="space-y-2">
              <div className="flex items-center gap-2 px-1">
                <h3 className="text-sm font-semibold text-gray-700 dark:text-slate-200">{group.owner}</h3>
                <span className="text-xs text-gray-400 dark:text-slate-500">{group.repos.length}</span>
              </div>

              <div className="space-y-2">
                {group.repos.map(repo => {
                  const key = `${repo.owner}/${repo.name}`;
                  const isToggling = togglingRepo === key;

                  return (
                    <div key={key} className="bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-xl overflow-hidden">
                      <div className="p-4 flex items-center gap-3">
                        <div className="flex-1 min-w-0">
                          <div className="flex items-center gap-2">
                            <p className="font-medium text-sm truncate">{repo.name}</p>
                            <span className={`text-[10px] font-medium px-1.5 py-0.5 rounded-full shrink-0 ${
                              repo.isPrivate
                                ? "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300"
                                : "bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300"
                            }`}>
                              {repo.isPrivate ? "Private" : "Public"}
                            </span>
                          </div>
                          {repo.claimedByOther && (
                            <span className="inline-flex items-center gap-1 text-xs text-amber-600 dark:text-amber-400"><Lock size={12} /> Claimed by another user</span>
                          )}
                          {repo.isEnabled && !repo.claimedByOther && (
                            <span className="block text-xs text-gray-500 dark:text-slate-400 mt-0.5" title="Estimated total EC2 cost for this repo's previews">
                              Est. cost: {formatUsd(repo.costUsd)}
                            </span>
                          )}
                        </div>
                        <div className="flex items-center gap-2">
                          {repo.isEnabled && !repo.claimedByOther && (
                            <button
                              onClick={() => navigate(`/repos/${repo.owner}/${repo.name}`)}
                              className="inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium border border-gray-300 dark:border-slate-600 rounded-lg hover:bg-gray-50 dark:hover:bg-slate-700 transition-colors"
                            >
                              <Settings size={14} /> Configure
                            </button>
                          )}
                          {!repo.claimedByOther && (
                            <button
                              onClick={() => handleToggle(repo)}
                              disabled={isToggling}
                              className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
                                repo.isEnabled ? "bg-blue-600" : "bg-gray-300 dark:bg-slate-600"
                              } disabled:opacity-50`}
                              title={repo.isEnabled ? "Disable previews" : "Enable previews"}
                            >
                              <span className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${repo.isEnabled ? "translate-x-6" : "translate-x-1"}`} />
                            </button>
                          )}
                        </div>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          ))}
        </section>
      ))}
    </div>
  );
}

function groupReposByOwner(repos: Repo[]) {
  const ownerMap = new Map<string, Repo[]>();
  for (const repo of repos) {
    ownerMap.set(repo.owner, [...(ownerMap.get(repo.owner) ?? []), repo]);
  }

  return [...ownerMap.entries()]
    .sort(([a], [b]) => a.localeCompare(b, undefined, { sensitivity: "base", numeric: true }))
    .map(([owner, ownerRepos]) => ({
      owner,
      repos: ownerRepos.sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: "base", numeric: true })),
    }));
}

const inputCls = "w-full px-3 py-2 text-sm border border-gray-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 focus:outline-none focus:ring-2 focus:ring-blue-500";
