import { useState, useEffect, useRef, useCallback } from "react";
import { Device, Call } from "@twilio/voice-sdk";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Phone, PhoneOff, Mic, MicOff, Delete } from "lucide-react";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";

type CallStatus = "idle" | "requesting-token" | "connecting" | "connected" | "error";

const KEYS = [
  ["1", "2", "3"],
  ["4", "5", "6"],
  ["7", "8", "9"],
  ["*", "0", "#"],
];

function formatDuration(seconds: number): string {
  const m = Math.floor(seconds / 60).toString().padStart(2, "0");
  const s = (seconds % 60).toString().padStart(2, "0");
  return `${m}:${s}`;
}

export function DialPad() {
  const [dialedNumber, setDialedNumber] = useState("");
  const [status, setStatus] = useState<CallStatus>("idle");
  const [isMuted, setIsMuted] = useState(false);
  const [duration, setDuration] = useState(0);
  const { toast } = useToast();

  const deviceRef = useRef<Device | null>(null);
  const callRef = useRef<Call | null>(null);
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const stopTimer = useCallback(() => {
    if (timerRef.current) {
      clearInterval(timerRef.current);
      timerRef.current = null;
    }
  }, []);

  const destroyDevice = useCallback(() => {
    callRef.current?.disconnect();
    callRef.current = null;
    deviceRef.current?.destroy();
    deviceRef.current = null;
  }, []);

  useEffect(() => {
    return () => {
      stopTimer();
      destroyDevice();
    };
  }, [stopTimer, destroyDevice]);

  // Keyboard input support
  useEffect(() => {
    const handleKey = (e: KeyboardEvent) => {
      if (status !== "idle") return;
      const valid = "0123456789*#";
      if (valid.includes(e.key)) {
        setDialedNumber((n) => (n.length < 16 ? n + e.key : n));
      } else if (e.key === "Backspace") {
        setDialedNumber((n) => n.slice(0, -1));
      }
    };
    window.addEventListener("keydown", handleKey);
    return () => window.removeEventListener("keydown", handleKey);
  }, [status]);

  const pressKey = (key: string) => {
    if (status !== "idle") return;
    setDialedNumber((n) => (n.length < 16 ? n + key : n));
  };

  const handleBackspace = () => {
    if (status !== "idle") return;
    setDialedNumber((n) => n.slice(0, -1));
  };

  const handleCall = async () => {
    if (!dialedNumber.trim()) {
      toast({ title: "Enter a number", description: "Please dial a phone number first.", variant: "destructive" });
      return;
    }

    setStatus("requesting-token");
    setDuration(0);
    setIsMuted(false);

    try {
      const res = await apiRequest("POST", "/api/twilio/voice-token");
      if (!res.ok) {
        const err = await res.json().catch(() => null);
        throw new Error(err?.message || "Failed to get voice token");
      }
      const { token } = await res.json();

      const device = new Device(token, { logLevel: "error" });
      deviceRef.current = device;

      await device.register();
      setStatus("connecting");

      // Normalize to E.164 if it looks like a 10-digit US number
      let toNumber = dialedNumber.replace(/\D/g, "");
      if (toNumber.length === 10) toNumber = "+1" + toNumber;
      else if (!toNumber.startsWith("+")) toNumber = "+" + toNumber;

      const call = await device.connect({ params: { To: toNumber } });
      callRef.current = call;

      call.on("accept", () => {
        setStatus("connected");
        timerRef.current = setInterval(() => setDuration((d) => d + 1), 1000);
      });

      call.on("disconnect", () => {
        stopTimer();
        destroyDevice();
        setStatus("idle");
        setDuration(0);
        setIsMuted(false);
      });

      call.on("error", (err: any) => {
        stopTimer();
        destroyDevice();
        setStatus("error");
        toast({ title: "Call Error", description: err?.message || "Call failed.", variant: "destructive" });
        setTimeout(() => setStatus("idle"), 3000);
      });
    } catch (err: any) {
      destroyDevice();
      setStatus("error");
      toast({ title: "Call Failed", description: err?.message || "Unable to place call.", variant: "destructive" });
      setTimeout(() => setStatus("idle"), 3000);
    }
  };

  const handleHangup = () => {
    callRef.current?.disconnect();
  };

  const handleMute = () => {
    if (!callRef.current) return;
    const next = !isMuted;
    callRef.current.mute(next);
    setIsMuted(next);
  };

  const statusLabel: Record<CallStatus, string> = {
    idle: "Ready",
    "requesting-token": "Initializing...",
    connecting: "Connecting...",
    connected: `In Call  ${formatDuration(duration)}`,
    error: "Error",
  };

  const statusColor: Record<CallStatus, string> = {
    idle: "text-muted-foreground",
    "requesting-token": "text-amber-500",
    connecting: "text-amber-500",
    connected: "text-green-600",
    error: "text-red-500",
  };

  const isInCall = status === "connected" || status === "connecting";
  const isBusy = status === "requesting-token" || status === "connecting";

  return (
    <Card>
      <CardHeader className="pb-3">
        <CardTitle className="text-base flex items-center gap-2">
          <Phone className="h-4 w-4" />
          Dial Pad
        </CardTitle>
      </CardHeader>
      <CardContent>
        <div className="flex flex-col items-center gap-3 max-w-xs mx-auto">
          {/* Number display */}
          <div className="w-full flex items-center gap-2 px-3 py-2 border rounded-lg bg-gray-50 min-h-[42px]">
            <span className="flex-1 font-mono text-lg tracking-widest text-center">
              {dialedNumber || <span className="text-muted-foreground text-sm">Enter number</span>}
            </span>
            {dialedNumber && status === "idle" && (
              <button onClick={handleBackspace} className="text-muted-foreground hover:text-foreground">
                <Delete className="h-4 w-4" />
              </button>
            )}
          </div>

          {/* Keypad */}
          <div className="grid grid-cols-3 gap-2 w-full">
            {KEYS.flat().map((key) => (
              <button
                key={key}
                onClick={() => pressKey(key)}
                disabled={isInCall || isBusy}
                className="h-12 rounded-lg border bg-white text-lg font-medium hover:bg-gray-50 active:bg-gray-100 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
              >
                {key}
              </button>
            ))}
          </div>

          {/* Call / Hangup */}
          <div className="flex gap-3 w-full">
            {!isInCall ? (
              <Button
                className="flex-1 bg-green-600 hover:bg-green-700 text-white"
                onClick={handleCall}
                disabled={isBusy || !dialedNumber.trim()}
              >
                <Phone className="h-4 w-4 mr-2" />
                Call
              </Button>
            ) : (
              <>
                <Button
                  variant="outline"
                  onClick={handleMute}
                  className={isMuted ? "border-red-300 text-red-600" : ""}
                >
                  {isMuted ? <MicOff className="h-4 w-4" /> : <Mic className="h-4 w-4" />}
                </Button>
                <Button
                  className="flex-1 bg-red-600 hover:bg-red-700 text-white"
                  onClick={handleHangup}
                >
                  <PhoneOff className="h-4 w-4 mr-2" />
                  Hang Up
                </Button>
              </>
            )}
          </div>

          {/* Status */}
          <p className={`text-sm font-medium ${statusColor[status]}`}>
            {statusLabel[status]}
          </p>
        </div>
      </CardContent>
    </Card>
  );
}
