import { type ReactElement, type SVGProps, useEffect, useState } from 'react';
import { APIProvider } from '@vis.gl/react-google-maps';
import { AlertCircle, Briefcase, LogIn, ShieldAlert, UserPlus } from 'lucide-react';
import { Layout } from './components/Layout';
import { SearchSetup } from './components/SearchSetup';
import { Dashboard } from './components/Dashboard';
import { MapView } from './components/MapView';
import type { AppUser } from '../shared/types';
import { getLocalSessionUser, signInWithLocalAuth, signOutWithLocalAuth, signUpWithLocalAuth } from './lib/auth';
import { hasApiConfig } from './lib/api';

const GOOGLE_MAPS_API_KEY = import.meta.env.VITE_GOOGLE_MAPS_PLATFORM_KEY ?? '';
const hasValidMapsKey = Boolean(GOOGLE_MAPS_API_KEY) && GOOGLE_MAPS_API_KEY !== 'YOUR_API_KEY';

export default function App() {
  const [user, setUser] = useState<AppUser | null>(null);
  const [loading, setLoading] = useState(true);
  const [activeTab, setActiveTab] = useState<'setup' | 'dashboard' | 'map'>('setup');
  const [selectedJobIds, setSelectedJobIds] = useState<string[]>([]);
  const [authError, setAuthError] = useState<string | null>(null);
  const [authNotice, setAuthNotice] = useState<string | null>(null);
  const [isAuthenticating, setIsAuthenticating] = useState(false);
  const [authMode, setAuthMode] = useState<'sign_in' | 'sign_up'>('sign_in');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [displayName, setDisplayName] = useState('');

  useEffect(() => {
    let isMounted = true;

    const loadSession = async () => {
      try {
        const sessionUser = await getLocalSessionUser();

        if (!isMounted) {
          return;
        }

        setUser(sessionUser);
      } catch (error) {
        if (!isMounted) {
          return;
        }

        setAuthError(error instanceof Error ? error.message : 'Failed to load session.');
      } finally {
        if (isMounted) {
          setLoading(false);
        }
      }
    };

    void loadSession();

    return () => {
      isMounted = false;
    };
  }, []);

  const handleToggleJobSelection = (jobId: string) => {
    setSelectedJobIds((currentJobIds) =>
      currentJobIds.includes(jobId) ? currentJobIds.filter((currentJobId) => currentJobId !== jobId) : [...currentJobIds, jobId],
    );
  };

  const handleSelectCreatedJob = (jobId: string) => {
    setSelectedJobIds((currentJobIds) => (currentJobIds.includes(jobId) ? currentJobIds : [...currentJobIds, jobId]));
  };

  const handleShowSelectedOnMap = () => {
    if (selectedJobIds.length === 0) {
      return;
    }

    setActiveTab('map');
  };

  const handleClearSelectedJobs = () => {
    setSelectedJobIds([]);
  };

  const handleLogin = async () => {
    setAuthError(null);
    setAuthNotice(null);
    setIsAuthenticating(true);

    try {
      if (authMode === 'sign_up') {
        const nextUser = await signUpWithLocalAuth({
          email,
          password,
          displayName: displayName.trim() || undefined,
        });

        setUser(nextUser);
        setAuthNotice('Account created and signed in.');
        return;
      }

      const nextUser = await signInWithLocalAuth({
        email,
        password,
      });

      setUser(nextUser);
    } catch (error) {
      setAuthError(error instanceof Error ? error.message : 'Authentication failed.');
    } finally {
      setIsAuthenticating(false);
    }
  };

  const handleLogout = async () => {
    try {
      await signOutWithLocalAuth();
      setUser(null);
      setSelectedJobIds([]);
      setAuthNotice(null);
    } catch (error) {
      setAuthError(error instanceof Error ? error.message : 'Failed to sign out.');
    }
  };

  if (loading) {
    return (
      <div className="flex h-screen items-center justify-center bg-stone-50">
        <div className="h-8 w-8 animate-spin rounded-full border-4 border-emerald-500 border-t-transparent"></div>
      </div>
    );
  }

  if (!hasApiConfig) {
    return (
      <ConfigScreen
        icon={<ShieldAlert className="h-8 w-8" />}
        title="Local API Config Required"
        description="Add your local API base URL before running the app."
        steps={[
          'Start the local Fastify API server.',
          'Add VITE_API_BASE_URL to your local environment.',
          'Ensure the API can reach your local PostgreSQL database.',
          'Restart the Vite dev server after updating env vars.',
        ]}
        footer="The app now uses a local API, PostgreSQL, and local session auth."
      />
    );
  }

  if (!hasValidMapsKey) {
    return (
        <ConfigScreen
          icon={<MapIcon className="h-8 w-8" />}
          title="Google Maps API Key Required"
          description="Add a browser key for map rendering and a server key for the local search API."
        steps={[
          'Create a Google Maps Platform API key for the browser app.',
          'Set VITE_GOOGLE_MAPS_PLATFORM_KEY locally for the frontend.',
          'Set GOOGLE_MAPS_SERVER_KEY for the local API server.',
          'Enable Geocoding API and Places API in Google Cloud.',
        ]}
        footer="The app will start once the browser key is available."
      />
    );
  }

  if (!user) {
    return (
      <div className="flex h-screen flex-col items-center justify-center bg-stone-50 p-4">
        <div className="w-full max-w-md space-y-8 rounded-2xl bg-white p-8 shadow-xl">
          <div className="text-center">
            <div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-emerald-100 text-emerald-600">
              <Briefcase className="h-8 w-8" />
            </div>
            <h1 className="mt-6 text-3xl font-bold tracking-tight text-stone-900">Leads4less</h1>
            <p className="mt-2 text-stone-600">Create a local account to access your lead workspace.</p>
          </div>

          <div className="grid grid-cols-2 gap-2 rounded-xl bg-stone-100 p-1">
            <button
              type="button"
              onClick={() => {
                setAuthMode('sign_in');
                setAuthError(null);
                setAuthNotice(null);
              }}
              className={`rounded-lg px-3 py-2 text-sm font-semibold transition-all ${
                authMode === 'sign_in' ? 'bg-white text-stone-900 shadow-sm' : 'text-stone-500 hover:text-stone-900'
              }`}
            >
              Sign In
            </button>
            <button
              type="button"
              onClick={() => {
                setAuthMode('sign_up');
                setAuthError(null);
                setAuthNotice(null);
              }}
              className={`rounded-lg px-3 py-2 text-sm font-semibold transition-all ${
                authMode === 'sign_up' ? 'bg-white text-stone-900 shadow-sm' : 'text-stone-500 hover:text-stone-900'
              }`}
            >
              Create Account
            </button>
          </div>

          {authError && (
            <div className="flex items-start gap-3 rounded-xl border border-red-100 bg-red-50 p-4 text-sm text-red-700">
              <AlertCircle className="mt-0.5 h-5 w-5 flex-shrink-0" />
              <div>
                <p className="font-semibold">Authentication Error</p>
                <p className="mt-1 opacity-90">{authError}</p>
              </div>
            </div>
          )}

          {authNotice && (
            <div className="rounded-xl border border-emerald-100 bg-emerald-50 p-4 text-sm text-emerald-700">
              {authNotice}
            </div>
          )}

          <form
            className="space-y-4"
            onSubmit={(event) => {
              event.preventDefault();
              void handleLogin();
            }}
          >
            {authMode === 'sign_up' && (
              <div>
                <label className="mb-2 block text-sm font-semibold text-stone-700">Name</label>
                <input
                  type="text"
                  value={displayName}
                  onChange={(event) => setDisplayName(event.target.value)}
                  placeholder="Your name"
                  className="w-full rounded-xl border border-stone-200 bg-stone-50 px-4 py-3 text-sm outline-none transition-all focus:border-emerald-500 focus:ring-2 focus:ring-emerald-500"
                />
              </div>
            )}

            <div>
              <label className="mb-2 block text-sm font-semibold text-stone-700">Email</label>
              <input
                type="email"
                required
                value={email}
                onChange={(event) => setEmail(event.target.value)}
                placeholder="you@example.com"
                className="w-full rounded-xl border border-stone-200 bg-stone-50 px-4 py-3 text-sm outline-none transition-all focus:border-emerald-500 focus:ring-2 focus:ring-emerald-500"
              />
            </div>

            <div>
              <label className="mb-2 block text-sm font-semibold text-stone-700">Password</label>
              <input
                type="password"
                required
                minLength={6}
                value={password}
                onChange={(event) => setPassword(event.target.value)}
                placeholder="At least 6 characters"
                className="w-full rounded-xl border border-stone-200 bg-stone-50 px-4 py-3 text-sm outline-none transition-all focus:border-emerald-500 focus:ring-2 focus:ring-emerald-500"
              />
            </div>

            <button
              type="submit"
              disabled={isAuthenticating}
              className="flex w-full items-center justify-center gap-3 rounded-xl bg-emerald-600 px-4 py-3 text-sm font-semibold text-white shadow-sm transition-all hover:bg-emerald-700 focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
            >
              {isAuthenticating ? (
                <div className="h-5 w-5 animate-spin rounded-full border-2 border-white border-t-transparent"></div>
              ) : authMode === 'sign_up' ? (
                <UserPlus className="h-5 w-5" />
              ) : (
                <LogIn className="h-5 w-5" />
              )}
              {isAuthenticating
                ? authMode === 'sign_up'
                  ? 'Creating account...'
                  : 'Signing in...'
                : authMode === 'sign_up'
                  ? 'Create Account'
                  : 'Sign In'}
            </button>
          </form>
        </div>
      </div>
    );
  }

  return (
    <APIProvider apiKey={GOOGLE_MAPS_API_KEY} version="weekly">
      <Layout
        user={user}
        activeTab={activeTab}
        setActiveTab={setActiveTab}
        onLogout={() => void handleLogout()}
      >
        {activeTab === 'setup' && (
          <SearchSetup
            user={user}
            selectedJobIds={selectedJobIds}
            onToggleJobSelection={handleToggleJobSelection}
            onSelectCreatedJob={handleSelectCreatedJob}
            onShowSelectedOnMap={handleShowSelectedOnMap}
            onClearSelection={handleClearSelectedJobs}
          />
        )}
        {activeTab === 'dashboard' && <Dashboard user={user} />}
        {activeTab === 'map' && <MapView user={user} jobIds={selectedJobIds} />}
      </Layout>
    </APIProvider>
  );
}

function ConfigScreen(props: {
  icon: ReactElement;
  title: string;
  description: string;
  steps: string[];
  footer: string;
}) {
  const { icon, title, description, steps, footer } = props;

  return (
    <div className="flex h-screen items-center justify-center bg-stone-50 p-6 font-sans">
      <div className="w-full max-w-lg rounded-2xl bg-white p-8 text-center shadow-xl">
        <div className="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-red-100 text-red-600">
          {icon}
        </div>
        <h2 className="mb-4 text-2xl font-bold text-stone-900">{title}</h2>
        <p className="mb-6 text-left text-stone-600">{description}</p>
        <div className="mb-6 space-y-4 rounded-xl border border-stone-200 bg-stone-50 p-6 text-left">
          <p className="text-sm font-medium text-stone-900">Follow these steps:</p>
          <ol className="list-inside list-decimal space-y-2 text-sm text-stone-600">
            {steps.map((step) => (
              <li key={step}>{step}</li>
            ))}
          </ol>
        </div>
        <p className="text-xs text-stone-400">{footer}</p>
      </div>
    </div>
  );
}

function MapIcon(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      {...props}
      xmlns="http://www.w3.org/2000/svg"
      width="24"
      height="24"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
    >
      <polygon points="3 6 9 3 15 6 21 3 21 18 15 21 9 18 3 21" />
      <line x1="9" y1="3" x2="9" y2="18" />
      <line x1="15" y1="6" x2="15" y2="21" />
    </svg>
  );
}
