import { useState, useRef, useEffect } from "react";
import { Upload, Trash2, Plus, X, Save } from "lucide-react";

import {
  useServerMissions,
  useServerMissionRotation,
  useUpdateMissionRotation,
  useUploadMission,
  useDeleteMission,
  useServerConfigSection,
} from "@/hooks/useServerDetail";
import type { MissionRotationEntry } from "@/hooks/useServerDetail";
import { useAuthStore } from "@/store/auth.store";
import { useUIStore } from "@/store/ui.store";
import { logger } from "@/lib/logger";

interface MissionListProps {
  serverId: number;
}

const DIFFICULTY_OPTIONS = ["", "Recruit", "Regular", "Veteran", "Custom"];

interface UploadProgress {
  filename: string;
  done: boolean;
}

export function MissionList({ serverId }: MissionListProps) {
  const isAdmin = useAuthStore((s) => s.user?.role === "admin");
  const addNotification = useUIStore((s) => s.addNotification);

  const { data: missionsData, isLoading: missionsLoading } = useServerMissions(serverId);
  const { data: rotationData, isLoading: rotationLoading } = useServerMissionRotation(serverId);
  const { data: serverSection } = useServerConfigSection(serverId, "server");
  const updateRotation = useUpdateMissionRotation(serverId);
  const uploadMission = useUploadMission(serverId);
  const deleteMission = useDeleteMission(serverId);

  const fileInputRef = useRef<HTMLInputElement>(null);
  const [rotation, setRotation] = useState<MissionRotationEntry[]>([]);
  const [uploadProgress, setUploadProgress] = useState<UploadProgress[]>([]);

  // Sync rotation from query on load
  useEffect(() => {
    if (rotationData) setRotation(rotationData);
  }, [rotationData]);

  const configVersion = (serverSection?._meta as { config_version?: number })?.config_version ?? 0;

  const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(e.target.files ?? []);
    if (files.length === 0) return;

    const progress: UploadProgress[] = files.map((f) => ({ filename: f.name, done: false }));
    setUploadProgress(progress);

    try {
      for (let i = 0; i < files.length; i++) {
        await uploadMission.mutateAsync([files[i]]);
        setUploadProgress((prev) => prev.map((p, idx) => (idx === i ? { ...p, done: true } : p)));
      }
      addNotification({ type: "success", message: `${files.length} mission(s) uploaded` });
    } catch (err) {
      logger.error("MissionList", "Failed to upload missions: %s", err);
      addNotification({ type: "error", message: "Failed to upload one or more missions" });
    }

    setUploadProgress([]);
    if (fileInputRef.current) fileInputRef.current.value = "";
  };

  const handleDelete = async (filename: string) => {
    try {
      await deleteMission.mutateAsync(filename);
      addNotification({ type: "info", message: `Mission ${filename} deleted` });
    } catch (err) {
      logger.error("MissionList", "Failed to delete mission %s: %s", filename, err);
      addNotification({ type: "error", message: `Failed to delete ${filename}` });
    }
  };

  const addToRotation = (missionName: string) => {
    if (rotation.some((r) => r.name === missionName)) return;
    setRotation([...rotation, { name: missionName, difficulty: "" }]);
  };

  const removeFromRotation = (idx: number) => {
    setRotation(rotation.filter((_, i) => i !== idx));
  };

  const updateDifficulty = (idx: number, difficulty: string) => {
    setRotation(rotation.map((r, i) => (i === idx ? { ...r, difficulty } : r)));
  };

  const handleSaveRotation = async () => {
    try {
      await updateRotation.mutateAsync({ missions: rotation, config_version: configVersion });
      addNotification({ type: "success", message: "Mission rotation saved" });
    } catch (err) {
      logger.error("MissionList", "Failed to save rotation: %s", err);
      addNotification({ type: "error", message: "Failed to save mission rotation" });
    }
  };

  const handleClearRotation = () => setRotation([]);

  if (missionsLoading || rotationLoading) {
    return <div className="text-text-muted text-sm p-4">Loading missions...</div>;
  }

  const missions = missionsData?.missions ?? [];

  return (
    <div data-testid="mission-list" className="space-y-8">
      {/* Section A: Available Missions */}
      <div>
        <div className="flex items-center justify-between mb-3">
          <h3 className="text-text-primary font-semibold">
            Available Missions ({missions.length})
          </h3>
          {isAdmin && (
            <label className="btn-primary flex items-center gap-1.5 text-sm cursor-pointer">
              <Upload size={14} />
              Upload .pbo
              <input
                ref={fileInputRef}
                type="file"
                accept=".pbo"
                multiple
                onChange={handleUpload}
                className="hidden"
                disabled={uploadMission.isPending}
              />
            </label>
          )}
        </div>

        {uploadProgress.length > 0 && (
          <div className="mb-3 space-y-1">
            {uploadProgress.map((p) => (
              <div key={p.filename} className="flex items-center gap-2 text-sm text-text-secondary">
                {p.done ? (
                  <span className="text-green-400">✓</span>
                ) : (
                  <span className="animate-spin inline-block w-3 h-3 border border-accent border-t-transparent rounded-full" />
                )}
                {p.filename}
              </div>
            ))}
          </div>
        )}

        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b border-surface-overlay">
                <th className="text-left text-text-muted font-medium px-3 py-2">Mission Name</th>
                <th className="text-left text-text-muted font-medium px-3 py-2">Terrain</th>
                <th className="text-right text-text-muted font-medium px-3 py-2">Size</th>
                {isAdmin && (
                  <th className="text-right text-text-muted font-medium px-3 py-2">Actions</th>
                )}
              </tr>
            </thead>
            <tbody>
              {missions.length === 0 ? (
                <tr>
                  <td colSpan={isAdmin ? 4 : 3} className="text-text-muted text-center py-6">
                    No missions uploaded
                  </td>
                </tr>
              ) : (
                missions.map((mission) => (
                  <tr
                    key={mission.filename}
                    className="border-b border-surface-overlay/50 hover:bg-surface-overlay/30"
                  >
                    <td className="text-text-primary px-3 py-2">{mission.name}</td>
                    <td className="px-3 py-2">
                      {mission.terrain ? (
                        <span className="bg-accent/20 text-accent text-xs px-2 py-0.5 rounded">
                          {mission.terrain}
                        </span>
                      ) : (
                        <span className="text-text-muted text-xs">—</span>
                      )}
                    </td>
                    <td className="text-right font-mono text-text-muted text-xs px-3 py-2">
                      {formatSize(mission.size_bytes)}
                    </td>
                    {isAdmin && (
                      <td className="text-right px-3 py-2">
                        <div className="flex items-center justify-end gap-1">
                          <button
                            onClick={() => addToRotation(mission.name)}
                            disabled={rotation.some((r) => r.name === mission.name)}
                            className="btn-ghost text-xs flex items-center gap-1"
                            title="Add to rotation"
                          >
                            <Plus size={12} />
                            Rotation
                          </button>
                          <button
                            onClick={() => handleDelete(mission.filename)}
                            disabled={deleteMission.isPending}
                            className="btn-ghost text-status-crashed"
                            aria-label={`Delete ${mission.filename}`}
                          >
                            <Trash2 size={14} />
                          </button>
                        </div>
                      </td>
                    )}
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>
      </div>

      {/* Section B: Mission Rotation */}
      <div>
        <div className="flex items-center justify-between mb-3">
          <h3 className="text-text-primary font-semibold">
            Mission Rotation ({rotation.length})
          </h3>
          {isAdmin && (
            <div className="flex gap-2">
              <button
                onClick={handleClearRotation}
                className="btn-ghost text-sm text-status-crashed"
                disabled={rotation.length === 0}
              >
                Clear
              </button>
              <button
                onClick={handleSaveRotation}
                disabled={updateRotation.isPending}
                className="btn-primary flex items-center gap-1.5 text-sm"
              >
                <Save size={14} />
                {updateRotation.isPending ? "Saving..." : "Save Rotation"}
              </button>
            </div>
          )}
        </div>

        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b border-surface-overlay">
                <th className="text-left text-text-muted font-medium px-3 py-2">#</th>
                <th className="text-left text-text-muted font-medium px-3 py-2">Mission Name</th>
                <th className="text-left text-text-muted font-medium px-3 py-2">Terrain</th>
                <th className="text-left text-text-muted font-medium px-3 py-2">Difficulty</th>
                {isAdmin && (
                  <th className="text-right text-text-muted font-medium px-3 py-2">Remove</th>
                )}
              </tr>
            </thead>
            <tbody>
              {rotation.length === 0 ? (
                <tr>
                  <td colSpan={isAdmin ? 5 : 4} className="text-text-muted text-center py-6">
                    No missions in rotation. Add from Available above.
                  </td>
                </tr>
              ) : (
                rotation.map((entry, idx) => {
                  const missionFile = missions.find((m) => m.name === entry.name);
                  return (
                    <tr
                      key={`${entry.name}-${idx}`}
                      className="border-b border-surface-overlay/50 hover:bg-surface-overlay/30"
                    >
                      <td className="text-text-muted font-mono text-xs px-3 py-2">{idx + 1}</td>
                      <td className="text-text-primary px-3 py-2">{entry.name}</td>
                      <td className="px-3 py-2">
                        {missionFile?.terrain ? (
                          <span className="bg-accent/20 text-accent text-xs px-2 py-0.5 rounded">
                            {missionFile.terrain}
                          </span>
                        ) : (
                          <span className="text-text-muted text-xs">—</span>
                        )}
                      </td>
                      <td className="px-3 py-2">
                        {isAdmin ? (
                          <select
                            className="neu-input text-sm py-1"
                            value={entry.difficulty}
                            onChange={(e) => updateDifficulty(idx, e.target.value)}
                          >
                            {DIFFICULTY_OPTIONS.map((opt) => (
                              <option key={opt} value={opt}>
                                {opt || "Default"}
                              </option>
                            ))}
                          </select>
                        ) : (
                          <span className="text-text-secondary">{entry.difficulty || "Default"}</span>
                        )}
                      </td>
                      {isAdmin && (
                        <td className="text-right px-3 py-2">
                          <button
                            onClick={() => removeFromRotation(idx)}
                            className="btn-ghost text-status-crashed"
                            aria-label={`Remove ${entry.name} from rotation`}
                          >
                            <X size={14} />
                          </button>
                        </td>
                      )}
                    </tr>
                  );
                })
              )}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

function formatSize(bytes: number): string {
  if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${bytes} B`;
}
