"use client";

import { useState, useEffect, useCallback } from "react";
import { Card, Button, Badge, Toggle, Input, CardSkeleton, Modal } from "@/shared/components";
import { useParams } from "next/navigation";
import Link from "next/link";
import { format } from "date-fns";

export default function UserDetailPage() {
  const params = useParams();
  const id = params.id;

  const [user, setUser] = useState(null);
  const [limits, setLimits] = useState(null);
  const [apiKeys, setApiKeys] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [saving, setSaving] = useState(false);
  const [saveMessage, setSaveMessage] = useState("");
  const [generatingKey, setGeneratingKey] = useState(false);
  const [generatedKey, setGeneratedKey] = useState("");
  const [initializingLimits, setInitializingLimits] = useState(false);

  const [userPackage, setUserPackage] = useState(null);
  const [packages, setPackages] = useState([]);
  const [showPackageModal, setShowPackageModal] = useState(false);
  const [packageSaving, setPackageSaving] = useState(false);
  const [packageMessage, setPackageMessage] = useState("");

  const fetchData = useCallback(async () => {
    try {
      setError("");
      setLoading(true);
      const [userRes, limitsRes, keysRes, pkgRes] = await Promise.all([
        fetch(`/api/users/${id}`),
        fetch(`/api/users/${id}/limits`),
        fetch(`/api/keys?userId=${encodeURIComponent(id)}`),
        fetch(`/api/users/${id}/package`),
      ]);

      if (!userRes.ok) {
        const data = await userRes.json();
        throw new Error(data.error || "User not found");
      }

      const userData = await userRes.json();
      setUser(userData.user);

      if (limitsRes.ok) {
        const limitsData = await limitsRes.json();
        setLimits(limitsData.limits);
      }

      if (keysRes.ok) {
        const keysData = await keysRes.json();
        setApiKeys(keysData.keys || []);
      }

      if (pkgRes.ok) {
        const pkgData = await pkgRes.json();
        setUserPackage(pkgData.userPackage);
        setPackages(pkgData.packages || []);
      }
    } catch (err) {
      setError(err.message || "An error occurred");
    } finally {
      setLoading(false);
    }
  }, [id]);

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

  const handleLimitsChange = (field, value) => {
    setLimits((prev) => ({ ...prev, [field]: Number(value) }));
    setSaveMessage("");
  };

  const handleSaveLimits = async () => {
    setSaving(true);
    setSaveMessage("");
    try {
      const res = await fetch(`/api/users/${id}/limits`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(limits),
      });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || "Failed to save limits");
      }
      setSaveMessage("Limits saved successfully");
    } catch (err) {
      setSaveMessage(err.message);
    } finally {
      setSaving(false);
    }
  };

  const handleGenerateApiKey = async () => {
    setGeneratingKey(true);
    setGeneratedKey("");
    try {
      const res = await fetch(`/api/keys`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: `${user?.username || "user"}-default`,
          userId: id,
          comment: "Auto-generated from user detail page",
        }),
      });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || "Failed to generate API key");
      }
      const data = await res.json();
      setGeneratedKey(data.key);
      await fetchData();
    } catch (err) {
      setError(err.message);
    } finally {
      setGeneratingKey(false);
    }
  };

  const handleInitLimits = async () => {
    setInitializingLimits(true);
    setError("");
    try {
      const res = await fetch(`/api/users/${id}/limits`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({}),
      });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || "Failed to initialize limits");
      }
      const data = await res.json();
      setLimits(data.limits);
    } catch (err) {
      setError(err.message);
    } finally {
      setInitializingLimits(false);
    }
  };

  const handleRoleChange = async (newRole) => {
    try {
      const res = await fetch(`/api/users/${id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ role: newRole }),
      });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || "Failed to update role");
      }
      setUser((prev) => ({ ...prev, role: newRole }));
    } catch (err) {
      setError(err.message);
    }
  };

  const handleActiveToggle = async (checked) => {
    try {
      const res = await fetch(`/api/users/${id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ is_active: checked }),
      });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || "Failed to update status");
      }
      setUser((prev) => ({ ...prev, is_active: checked }));
    } catch (err) {
      setError(err.message);
    }
  };

  const handleSavePackage = async (packageId, overrides) => {
    setPackageSaving(true);
    setPackageMessage("");
    try {
      const res = await fetch(`/api/users/${id}/package`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ packageId, overrides }),
      });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || "Failed to save package");
      }
      const data = await res.json();
      setUserPackage(data.userPackage);
      setShowPackageModal(false);
      setPackageMessage("Package updated successfully");
      if (limits) {
        const limitsRes = await fetch(`/api/users/${id}/limits`);
        if (limitsRes.ok) {
          const limitsData = await limitsRes.json();
          setLimits(limitsData.limits);
        }
      }
    } catch (err) {
      setPackageMessage(err.message);
    } finally {
      setPackageSaving(false);
    }
  };

  if (loading) {
    return (
      <div className="flex min-w-0 flex-col gap-6 px-1 sm:px-0">
        <CardSkeleton />
        <CardSkeleton />
      </div>
    );
  }

  if (error && !user) {
    return (
      <div className="flex min-w-0 flex-col gap-6 px-1 sm:px-0">
        <Link href="/dashboard/users" className="text-sm text-primary hover:underline">
          Back to Users
        </Link>
        <Card>
          <div className="text-center py-12">
            <p className="text-red-500 mb-4">{error}</p>
            <Button variant="outline" onClick={fetchData}>
              Retry
            </Button>
          </div>
        </Card>
      </div>
    );
  }

  const statusVariant = user.is_approved ? "success" : user.is_active ? "warning" : "error";
  const statusLabel = user.is_approved ? "Approved" : user.is_active ? "Pending" : "Disabled";

  return (
    <div className="flex min-w-0 flex-col gap-6 px-1 sm:px-0">
      {/* Back link */}
      <Link
        href="/dashboard/users"
        className="text-sm text-primary hover:underline flex items-center gap-1 w-fit"
      >
        <span className="material-symbols-outlined text-[16px]">arrow_back</span>
        Back to Users
      </Link>

      {/* Error banner */}
      {error && (
        <div className="rounded-lg bg-red-500/10 border border-red-500/20 px-4 py-3 text-sm text-red-600 dark:text-red-400">
          {error}
          <button
            onClick={() => setError("")}
            className="ml-2 underline hover:no-underline"
          >
            Dismiss
          </button>
        </div>
      )}

      {/* User Info Card */}
      <Card
        title={user.username}
        subtitle={`Created ${format(new Date(user.created_at), "MMM d, yyyy")}`}
        icon="person"
        data-testid="user-detail-card"
      >
        <div className="flex flex-col gap-4">
          <div className="flex items-center gap-3 flex-wrap">
            <Badge variant={user.role === "admin" ? "primary" : "default"}>
              {user.role}
            </Badge>
            <Badge variant={statusVariant} dot>
              {statusLabel}
            </Badge>
          </div>

          {/* Role select */}
          <div className="flex items-center gap-3" data-testid="role-select">
            <label className="text-sm font-medium text-text-main">Role</label>
            <select
              value={user.role}
              onChange={(e) => handleRoleChange(e.target.value)}
              className="rounded-[10px] border border-border bg-surface-2 px-3 py-2 text-sm text-text-main focus:outline-none focus:ring-2 focus:ring-brand-500/30"
            >
              <option value="user">user</option>
              <option value="admin">admin</option>
            </select>
          </div>

          {/* Active toggle */}
          <div data-testid="active-toggle">
            <Toggle
              checked={user.is_active}
              onChange={handleActiveToggle}
              label="Active"
              description={user.is_active ? "User can log in" : "User is disabled"}
            />
          </div>
        </div>
      </Card>

      {/* Rate Limits */}
      <Card title="Rate Limits" icon="speed">
        {limits ? (
          <div className="flex flex-col gap-4" data-testid="limits-form">
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
              <Input
                label="Requests per Minute"
                type="number"
                value={limits.rtpMinute}
                onChange={(e) => handleLimitsChange("rtpMinute", e.target.value)}
                hint="Minimum: 1"
              />
              <Input
                label="Requests per Day"
                type="number"
                value={limits.rtpDay}
                onChange={(e) => handleLimitsChange("rtpDay", e.target.value)}
                hint="Minimum: 1"
              />
              <Input
                label="Monthly Token Limit"
                type="number"
                value={limits.tokenLimitMonthly}
                onChange={(e) => handleLimitsChange("tokenLimitMonthly", e.target.value)}
                hint="Minimum: 1"
              />
              <Input
                label="Credit Limit ($)"
                type="number"
                value={limits.creditLimit}
                onChange={(e) => handleLimitsChange("creditLimit", e.target.value)}
                hint="Minimum: 0"
              />
              <Input
                label="Max Concurrent"
                type="number"
                value={limits.maxConcurrent}
                onChange={(e) => handleLimitsChange("maxConcurrent", e.target.value)}
                hint="Minimum: 1"
              />
            </div>

            <div className="flex items-center gap-3">
              <Button
                variant="primary"
                loading={saving}
                onClick={handleSaveLimits}
                data-testid="save-limits-btn"
              >
                Save Limits
              </Button>
              {saveMessage && (
                <span
                  className={`text-sm ${
                    saveMessage.includes("success")
                      ? "text-green-600 dark:text-green-400"
                      : "text-red-500"
                  }`}
                >
                  {saveMessage}
                </span>
              )}
            </div>
          </div>
        ) : (
          <div className="flex flex-col gap-3">
            <p className="text-sm text-text-muted">No rate limits configured for this user.</p>
            <Button
              variant="primary"
              icon="add_circle"
              onClick={handleInitLimits}
              loading={initializingLimits}
              data-testid="init-limits-btn"
            >
              Initialize Rate Limits
            </Button>
          </div>
        )}
      </Card>

      {/* Package */}
      <Card title="Package" icon="inventory_2" data-testid="package-card">
        <div className="flex flex-col gap-4">
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
            <div>
              <label className="text-xs font-medium text-text-muted uppercase tracking-wider">Package Name</label>
              <p className="text-sm text-text-main mt-1">
                {userPackage?.packageName || <span className="text-text-muted italic">None</span>}
              </p>
            </div>
            <div>
              <label className="text-xs font-medium text-text-muted uppercase tracking-wider">Expiry Date</label>
              <p className="text-sm text-text-main mt-1">
                {userPackage?.expiresAt
                  ? format(new Date(userPackage.expiresAt), "MMM d, yyyy")
                  : <span className="text-text-muted italic">No expiry</span>}
              </p>
            </div>
            <div>
              <label className="text-xs font-medium text-text-muted uppercase tracking-wider">Assigned</label>
              <p className="text-sm text-text-main mt-1">
                {userPackage?.assignedAt
                  ? format(new Date(userPackage.assignedAt), "MMM d, yyyy")
                  : <span className="text-text-muted italic">-</span>}
              </p>
            </div>
            <div>
              <label className="text-xs font-medium text-text-muted uppercase tracking-wider">Effective Limits</label>
              <p className="text-sm text-text-main mt-1">
                {userPackage
                  ? `${userPackage.rtpMinute} RPM / ${userPackage.maxConcurrent} concurrent`
                  : <span className="text-text-muted italic">-</span>}
              </p>
            </div>
          </div>

          <div className="flex items-center gap-3">
            <Button
              variant="outline"
              icon="swap_horiz"
              onClick={() => setShowPackageModal(true)}
              data-testid="change-package-btn"
            >
              Change Package
            </Button>
            {packageMessage && (
              <span
                className={`text-sm ${
                  packageMessage.includes("success")
                    ? "text-green-600 dark:text-green-400"
                    : "text-red-500"
                }`}
              >
                {packageMessage}
              </span>
            )}
          </div>
        </div>
      </Card>

      {/* API Keys */}
      <Card title="API Keys" icon="key">
        {apiKeys.length === 0 ? (
          <div className="flex flex-col gap-3">
            <p className="text-sm text-text-muted">No API keys for this user.</p>
            <Button
              variant="primary"
              icon="key"
              onClick={handleGenerateApiKey}
              loading={generatingKey}
              data-testid="generate-api-key-btn"
            >
              Generate API Key
            </Button>
            {generatedKey && (
              <div className="mt-2 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg border border-green-200 dark:border-green-800">
                <p className="text-sm font-medium text-green-800 dark:text-green-200 mb-2">API Key Generated!</p>
                <code className="text-xs bg-white dark:bg-gray-800 p-2 rounded block break-all">{generatedKey}</code>
                <Button
                  size="sm"
                  variant="ghost"
                  className="mt-2"
                  onClick={() => navigator.clipboard.writeText(generatedKey)}
                >
                  Copy Key
                </Button>
              </div>
            )}
          </div>
        ) : (
          <div className="flex flex-col gap-2">
            {apiKeys.map((key) => (
              <div
                key={key.id}
                className="flex items-center justify-between rounded-lg bg-surface-2 px-3 py-2 text-sm"
              >
                <div className="min-w-0 flex-1">
                  <div className="flex items-center gap-2">
                    <span className="text-xs font-medium text-text-main truncate">{key.name}</span>
                    {!key.isActive && (
                      <Badge variant="error" size="sm" dot>Disabled</Badge>
                    )}
                  </div>
                  <code className="text-xs text-text-muted truncate block mt-0.5">{key.key}</code>
                  {key.comment && (
                    <p className="text-[10px] text-text-muted italic mt-0.5">{key.comment}</p>
                  )}
                  <span className="text-[10px] text-text-muted">
                    Created {format(new Date(key.createdAt), "MMM d, yyyy")}
                  </span>
                </div>
              </div>
            ))}
          </div>
        )}
      </Card>

      <PackageSelectorModal
        isOpen={showPackageModal}
        onClose={() => {
          setShowPackageModal(false);
          setPackageMessage("");
        }}
        packages={packages}
        userPackage={userPackage}
        onSave={handleSavePackage}
        saving={packageSaving}
      />
    </div>
  );
}

function PackageSelectorModal({ isOpen, onClose, packages, userPackage, onSave, saving }) {
  const [selectedPackageId, setSelectedPackageId] = useState("");
  const [overrides, setOverrides] = useState({
    rtpMinuteOverride: "",
    rtpDayOverride: "",
    tokenLimitMonthlyOverride: "",
    creditLimitOverride: "",
    maxConcurrentOverride: "",
  });

  useEffect(() => {
    if (isOpen) {
      const pkgId = userPackage?.packageId || "";
      setSelectedPackageId(pkgId);
      setOverrides({
        rtpMinuteOverride: userPackage?.rtpMinuteOverride ?? "",
        rtpDayOverride: userPackage?.rtpDayOverride ?? "",
        tokenLimitMonthlyOverride: userPackage?.tokenLimitMonthlyOverride ?? "",
        creditLimitOverride: userPackage?.creditLimitOverride ?? "",
        maxConcurrentOverride: userPackage?.maxConcurrentOverride ?? "",
      });
    }
  }, [isOpen, userPackage]);

  const selectedPkg = packages.find((p) => p.id === selectedPackageId);

  const handleOverrideChange = (field, value) => {
    setOverrides((prev) => ({ ...prev, [field]: value }));
  };

  const handleSave = () => {
    const cleanOverrides = {};
    for (const [key, val] of Object.entries(overrides)) {
      if (val !== "" && val !== null && val !== undefined) {
        cleanOverrides[key] = Number(val);
      }
    }
    onSave(selectedPackageId, cleanOverrides);
  };

  return (
    <Modal
      isOpen={isOpen}
      onClose={onClose}
      title="Change Package"
      size="lg"
      footer={
        <>
          <Button variant="ghost" onClick={onClose} disabled={saving}>
            Cancel
          </Button>
          <Button
            variant="primary"
            onClick={handleSave}
            loading={saving}
            disabled={!selectedPackageId}
            data-testid="save-package-btn"
          >
            Save Package
          </Button>
        </>
      }
    >
      <div className="flex flex-col gap-6">
        <div>
          <label className="text-sm font-medium text-text-main mb-2 block">Select Package</label>
          <div className="flex flex-col gap-2" data-testid="package-list">
            {packages.length === 0 ? (
              <p className="text-sm text-text-muted">No packages available.</p>
            ) : (
              packages.map((pkg) => (
                <button
                  key={pkg.id}
                  type="button"
                  onClick={() => setSelectedPackageId(pkg.id)}
                  className={`text-left rounded-[10px] border p-3 transition-all ${
                    selectedPackageId === pkg.id
                      ? "border-brand-500 bg-brand-500/5"
                      : "border-border hover:border-brand-500/40 hover:bg-surface-2"
                  }`}
                >
                  <div className="flex items-center justify-between">
                    <div>
                      <p className="text-sm font-medium text-text-main">{pkg.name}</p>
                      {pkg.description && (
                        <p className="text-xs text-text-muted mt-0.5">{pkg.description}</p>
                      )}
                    </div>
                    {selectedPackageId === pkg.id && (
                      <span className="material-symbols-outlined text-brand-500 text-[20px]">check_circle</span>
                    )}
                  </div>
                  <div className="flex flex-wrap gap-x-4 gap-y-1 mt-2 text-xs text-text-muted">
                    <span>{pkg.rtpMinute} RPM</span>
                    <span>{pkg.rtpDay} RPD</span>
                    <span>{pkg.tokenLimitMonthly?.toLocaleString()} tokens</span>
                    <span>${pkg.creditLimit} credit</span>
                    <span>{pkg.maxConcurrent} concurrent</span>
                    {pkg.durationDays && <span>{pkg.durationDays} days</span>}
                  </div>
                </button>
              ))
            )}
          </div>
        </div>

        {selectedPkg && (
          <div>
            <label className="text-sm font-medium text-text-main mb-2 block">
              Per-User Overrides
              <span className="text-xs text-text-muted font-normal ml-2">Leave empty to use package defaults</span>
            </label>
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
              <Input
                label="RPM Override"
                type="number"
                value={overrides.rtpMinuteOverride}
                onChange={(e) => handleOverrideChange("rtpMinuteOverride", e.target.value)}
                placeholder={`Default: ${selectedPkg.rtpMinute}`}
                hint="Leave empty for default"
              />
              <Input
                label="RPD Override"
                type="number"
                value={overrides.rtpDayOverride}
                onChange={(e) => handleOverrideChange("rtpDayOverride", e.target.value)}
                placeholder={`Default: ${selectedPkg.rtpDay}`}
                hint="Leave empty for default"
              />
              <Input
                label="Token Limit Override"
                type="number"
                value={overrides.tokenLimitMonthlyOverride}
                onChange={(e) => handleOverrideChange("tokenLimitMonthlyOverride", e.target.value)}
                placeholder={`Default: ${selectedPkg.tokenLimitMonthly?.toLocaleString()}`}
                hint="Leave empty for default"
              />
              <Input
                label="Credit Limit Override"
                type="number"
                value={overrides.creditLimitOverride}
                onChange={(e) => handleOverrideChange("creditLimitOverride", e.target.value)}
                placeholder={`Default: ${selectedPkg.creditLimit}`}
                hint="Leave empty for default"
              />
              <Input
                label="Max Concurrent Override"
                type="number"
                value={overrides.maxConcurrentOverride}
                onChange={(e) => handleOverrideChange("maxConcurrentOverride", e.target.value)}
                placeholder={`Default: ${selectedPkg.maxConcurrent}`}
                hint="Leave empty for default"
              />
            </div>
          </div>
        )}
      </div>
    </Modal>
  );
}
