import { useState, useEffect, useCallback, useRef } from 'react';
import { createLogger } from '@automaker/utils/logger';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { useSetupStore } from '@/store/setup-store';
import { getElectronAPI } from '@/lib/electron';
import {
  CheckCircle2,
  ArrowRight,
  ArrowLeft,
  ExternalLink,
  Copy,
  RefreshCw,
  AlertTriangle,
  XCircle,
  Terminal,
} from 'lucide-react';
import { Spinner } from '@/components/ui/spinner';
import { toast } from 'sonner';
import { StatusBadge } from '../components';

const logger = createLogger('OpencodeSetupStep');

interface OpencodeSetupStepProps {
  onNext: () => void;
  onBack: () => void;
  onSkip: () => void;
}

interface OpencodeCliStatus {
  installed: boolean;
  version?: string | null;
  path?: string | null;
  auth?: {
    authenticated: boolean;
    method: string;
  };
  installCommand?: string;
  loginCommand?: string;
}

export function OpencodeSetupStep({ onNext, onBack, onSkip }: OpencodeSetupStepProps) {
  const { opencodeCliStatus, setOpencodeCliStatus } = useSetupStore();
  const [isChecking, setIsChecking] = useState(false);
  const [isLoggingIn, setIsLoggingIn] = useState(false);
  const pollIntervalRef = useRef<NodeJS.Timeout | null>(null);

  const checkStatus = useCallback(async () => {
    setIsChecking(true);
    try {
      const api = getElectronAPI();
      if (!api.setup?.getOpencodeStatus) {
        return;
      }
      const result = await api.setup.getOpencodeStatus();
      if (result.success) {
        // Derive install command from platform-specific options or use npm fallback
        const installCommand =
          result.installCommands?.npm ||
          result.installCommands?.macos ||
          result.installCommands?.linux;
        const status: OpencodeCliStatus = {
          installed: result.installed ?? false,
          version: result.version ?? null,
          path: result.path ?? null,
          auth: result.auth,
          installCommand,
          loginCommand: 'opencode auth login',
        };
        setOpencodeCliStatus(status);

        if (result.auth?.authenticated) {
          toast.success('OpenCode CLI is ready!');
        }
      }
    } catch (error) {
      logger.error('Failed to check OpenCode status:', error);
    } finally {
      setIsChecking(false);
    }
  }, [setOpencodeCliStatus]);

  useEffect(() => {
    checkStatus();
    // Cleanup polling on unmount
    return () => {
      if (pollIntervalRef.current) {
        clearInterval(pollIntervalRef.current);
      }
    };
  }, [checkStatus]);

  const copyCommand = (command: string) => {
    navigator.clipboard.writeText(command);
    toast.success('Command copied to clipboard');
  };

  const handleLogin = async () => {
    setIsLoggingIn(true);

    try {
      // Copy login command to clipboard and show instructions
      const loginCommand = opencodeCliStatus?.loginCommand || 'opencode auth login';
      await navigator.clipboard.writeText(loginCommand);
      toast.info('Login command copied! Paste in terminal to authenticate.');

      // Poll for auth status
      let attempts = 0;
      const maxAttempts = 60; // 2 minutes with 2s interval

      pollIntervalRef.current = setInterval(async () => {
        attempts++;

        try {
          const api = getElectronAPI();
          if (!api.setup?.getOpencodeStatus) {
            return;
          }
          const result = await api.setup.getOpencodeStatus();

          if (result.auth?.authenticated) {
            if (pollIntervalRef.current) {
              clearInterval(pollIntervalRef.current);
              pollIntervalRef.current = null;
            }
            setOpencodeCliStatus({
              ...opencodeCliStatus,
              installed: result.installed ?? true,
              version: result.version,
              path: result.path,
              auth: result.auth,
            } as OpencodeCliStatus);
            setIsLoggingIn(false);
            toast.success('Successfully logged in to OpenCode!');
          }
        } catch {
          // Ignore polling errors
        }

        if (attempts >= maxAttempts) {
          if (pollIntervalRef.current) {
            clearInterval(pollIntervalRef.current);
            pollIntervalRef.current = null;
          }
          setIsLoggingIn(false);
          toast.error('Login timed out. Please try again.');
        }
      }, 2000);
    } catch (error) {
      logger.error('Login failed:', error);
      toast.error('Failed to start login process');
      setIsLoggingIn(false);
    }
  };

  const isReady = opencodeCliStatus?.installed && opencodeCliStatus?.auth?.authenticated;

  const getStatusBadge = () => {
    if (isChecking) {
      return <StatusBadge status="checking" label="Checking..." />;
    }
    if (opencodeCliStatus?.auth?.authenticated) {
      return <StatusBadge status="authenticated" label="Ready" />;
    }
    if (opencodeCliStatus?.installed) {
      return <StatusBadge status="unverified" label="Not Logged In" />;
    }
    return <StatusBadge status="not_installed" label="Not Installed" />;
  };

  return (
    <div className="space-y-6">
      <div className="text-center mb-8">
        <div className="w-16 h-16 rounded-xl bg-green-500/10 flex items-center justify-center mx-auto mb-4">
          <Terminal className="w-8 h-8 text-green-500" />
        </div>
        <h2 className="text-2xl font-bold text-foreground mb-2">OpenCode CLI Setup</h2>
        <p className="text-muted-foreground">Optional - Use OpenCode as an AI provider</p>
      </div>

      {/* Info Banner */}
      <Card className="bg-green-500/10 border-green-500/20">
        <CardContent className="pt-4">
          <div className="flex items-start gap-3">
            <AlertTriangle className="w-5 h-5 text-green-500 shrink-0 mt-0.5" />
            <div>
              <p className="font-medium text-foreground">This step is optional</p>
              <p className="text-sm text-muted-foreground mt-1">
                Configure OpenCode CLI for access to free tier models and connected providers. You
                can skip this and use other providers, or configure it later in Settings.
              </p>
            </div>
          </div>
        </CardContent>
      </Card>

      {/* Status Card */}
      <Card className="bg-card border-border">
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle className="text-lg flex items-center gap-2">
              <Terminal className="w-5 h-5" />
              OpenCode CLI Status
              <Badge variant="outline" className="ml-2">
                Optional
              </Badge>
            </CardTitle>
            <div className="flex items-center gap-2">
              {getStatusBadge()}
              <Button variant="ghost" size="sm" onClick={checkStatus} disabled={isChecking}>
                {isChecking ? <Spinner size="sm" /> : <RefreshCw className="w-4 h-4" />}
              </Button>
            </div>
          </div>
          <CardDescription>
            {opencodeCliStatus?.installed
              ? opencodeCliStatus.auth?.authenticated
                ? `Authenticated via ${opencodeCliStatus.auth.method === 'api_key' ? 'API Key' : 'Browser Login'}${opencodeCliStatus.version ? ` (v${opencodeCliStatus.version})` : ''}`
                : 'Installed but not authenticated'
              : 'Not installed on your system'}
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          {/* Success State */}
          {isReady && (
            <div className="flex items-center gap-3 p-4 rounded-lg bg-green-500/10 border border-green-500/20">
              <CheckCircle2 className="w-5 h-5 text-green-500" />
              <div>
                <p className="font-medium text-foreground">OpenCode CLI is ready!</p>
                <p className="text-sm text-muted-foreground">
                  You can use OpenCode models for AI tasks.
                  {opencodeCliStatus?.version && (
                    <span className="ml-1">Version: {opencodeCliStatus.version}</span>
                  )}
                </p>
              </div>
            </div>
          )}

          {/* Not Installed */}
          {!opencodeCliStatus?.installed && !isChecking && (
            <div className="space-y-4">
              <div className="flex items-start gap-3 p-4 rounded-lg bg-muted/30 border border-border">
                <XCircle className="w-5 h-5 text-muted-foreground shrink-0 mt-0.5" />
                <div className="flex-1">
                  <p className="font-medium text-foreground">OpenCode CLI not found</p>
                  <p className="text-sm text-muted-foreground mt-1">
                    Install the OpenCode CLI to use free tier models and connected providers.
                  </p>
                </div>
              </div>

              <div className="space-y-3 p-4 rounded-lg bg-muted/30 border border-border">
                <p className="font-medium text-foreground text-sm">Install OpenCode CLI:</p>
                <div className="flex items-center gap-2">
                  <code className="flex-1 bg-muted px-3 py-2 rounded text-sm font-mono text-foreground overflow-x-auto">
                    {opencodeCliStatus?.installCommand || 'npm install -g opencode'}
                  </code>
                  <Button
                    variant="ghost"
                    size="icon"
                    onClick={() =>
                      copyCommand(opencodeCliStatus?.installCommand || 'npm install -g opencode')
                    }
                  >
                    <Copy className="w-4 h-4" />
                  </Button>
                </div>
                <a
                  href="https://github.com/opencode-ai/opencode"
                  target="_blank"
                  rel="noopener noreferrer"
                  className="inline-flex items-center text-sm text-brand-500 hover:underline mt-2"
                >
                  View installation docs
                  <ExternalLink className="w-3 h-3 ml-1" />
                </a>
              </div>
            </div>
          )}

          {/* Installed but not authenticated */}
          {opencodeCliStatus?.installed &&
            !opencodeCliStatus?.auth?.authenticated &&
            !isChecking && (
              <div className="space-y-4">
                <div className="flex items-start gap-3 p-4 rounded-lg bg-amber-500/10 border border-amber-500/20">
                  <AlertTriangle className="w-5 h-5 text-amber-500 shrink-0 mt-0.5" />
                  <div className="flex-1">
                    <p className="font-medium text-foreground">OpenCode CLI not authenticated</p>
                    <p className="text-sm text-muted-foreground mt-1">
                      Run the login command to authenticate with OpenCode.
                    </p>
                  </div>
                </div>

                <div className="space-y-3 p-4 rounded-lg bg-muted/30 border border-border">
                  <p className="text-sm text-muted-foreground">
                    Run the login command in your terminal, then complete authentication in your
                    browser:
                  </p>
                  <div className="flex items-center gap-2">
                    <code className="flex-1 bg-muted px-3 py-2 rounded text-sm font-mono text-foreground">
                      {opencodeCliStatus?.loginCommand || 'opencode auth login'}
                    </code>
                    <Button
                      variant="ghost"
                      size="icon"
                      onClick={() =>
                        copyCommand(opencodeCliStatus?.loginCommand || 'opencode auth login')
                      }
                    >
                      <Copy className="w-4 h-4" />
                    </Button>
                  </div>
                  <Button
                    onClick={handleLogin}
                    disabled={isLoggingIn}
                    className="w-full bg-brand-500 hover:bg-brand-600 text-white"
                  >
                    {isLoggingIn ? (
                      <>
                        <Spinner size="sm" variant="foreground" className="mr-2" />
                        Waiting for login...
                      </>
                    ) : (
                      'Copy Command & Wait for Login'
                    )}
                  </Button>
                </div>
              </div>
            )}

          {/* Loading State */}
          {isChecking && (
            <div className="flex items-center gap-3 p-4 rounded-lg bg-blue-500/10 border border-blue-500/20">
              <Spinner size="md" />
              <div>
                <p className="font-medium text-foreground">Checking OpenCode CLI status...</p>
              </div>
            </div>
          )}
        </CardContent>
      </Card>

      {/* Navigation */}
      <div className="flex justify-between pt-4">
        <Button variant="ghost" onClick={onBack} className="text-muted-foreground">
          <ArrowLeft className="w-4 h-4 mr-2" />
          Back
        </Button>
        <div className="flex gap-2">
          <Button variant="ghost" onClick={onSkip} className="text-muted-foreground">
            {isReady ? 'Skip' : 'Skip for now'}
          </Button>
          <Button
            onClick={onNext}
            className="bg-brand-500 hover:bg-brand-600 text-white"
            data-testid="opencode-next-button"
          >
            {isReady ? 'Continue' : 'Continue without OpenCode'}
            <ArrowRight className="w-4 h-4 ml-2" />
          </Button>
        </div>
      </div>

      {/* Info note */}
      <p className="text-xs text-muted-foreground text-center">
        You can always configure OpenCode later in Settings
      </p>
    </div>
  );
}
