import React, { useState, useRef } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/contexts/AuthContext';
import { Navigate } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { useToast } from '@/hooks/use-toast';
import { Loader2, Database, Users, CheckCircle, XCircle, AlertTriangle, Upload, KeyRound, CheckSquare } from 'lucide-react';
import { Checkbox } from '@/components/ui/checkbox';
import { Progress } from '@/components/ui/progress';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';

export default function DataMigration() {
  const { isAdmin, loading: authLoading, session } = useAuth();
  const { toast } = useToast();
  const [step, setStep] = useState('idle'); // idle | scanning | scan_done | migrating_users | migrating_tables | done
  const [tableCounts, setTableCounts] = useState(null);
  const [userResults, setUserResults] = useState(null);
  const [tableResults, setTableResults] = useState(null);
  const [progress, setProgress] = useState(0);
  const [error, setError] = useState(null);
  const [csvUsers, setCsvUsers] = useState(null);
  const [importingCsv, setImportingCsv] = useState(false);
  const [csvResults, setCsvResults] = useState(null);
  const [selectedTables, setSelectedTables] = useState(new Set());
  const fileInputRef = useRef(null);

  const invokeMigrationFunction = async (body) => {
    const accessToken = session?.access_token;

    if (!accessToken) {
      throw new Error('Your session expired. Please sign in again and retry.');
    }

    return supabase.functions.invoke('migrate-from-source', {
      body,
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    });
  };

  if (authLoading) return null;
  if (!isAdmin && !authLoading) return <Navigate to="/dashboard" replace />;

  const scanSource = async () => {
    setStep('scanning');
    setError(null);
    try {
      const { data, error: fnErr } = await invokeMigrationFunction({ action: 'list_source_tables' });
      if (fnErr) throw fnErr;
      if (data?.error) throw new Error(data.error);
      setTableCounts(data.tables);
      // Auto-select all tables with data
      const withData = Object.entries(data.tables).filter(([_, c]) => c > 0).map(([name]) => name);
      setSelectedTables(new Set(withData));
      setStep('scan_done');
    } catch (e) {
      setError(e.message);
      setStep('idle');
      toast({ variant: 'destructive', title: 'Scan Failed', description: e.message });
    }
  };

  const migrateUsers = async () => {
    setStep('migrating_users');
    setError(null);
    try {
      const { data, error: fnErr } = await invokeMigrationFunction({ action: 'migrate_users' });
      if (fnErr) throw fnErr;
      if (data?.error) throw new Error(data.error);
      setUserResults(data.users);
      toast({ title: 'Users Migrated', description: `Created: ${data.users.created}, Skipped: ${data.users.skipped}` });
      setStep('scan_done');
    } catch (e) {
      setError(e.message);
      setStep('scan_done');
      toast({ variant: 'destructive', title: 'User Migration Failed', description: e.message });
    }
  };

  const handleCsvUpload = (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (evt) => {
      try {
        const text = evt.target.result;
        const lines = text.split('\n').filter(l => l.trim());
        if (lines.length < 2) throw new Error('CSV must have a header row and at least one data row');
        const headers = lines[0].split(',').map(h => h.trim().toLowerCase());
        const emailIdx = headers.indexOf('email');
        const passIdx = headers.findIndex(h => h === 'encrypted_password' || h === 'password_hash');
        if (emailIdx === -1) throw new Error('CSV must have an "email" column');
        if (passIdx === -1) throw new Error('CSV must have an "encrypted_password" or "password_hash" column');
        const users = lines.slice(1).map(line => {
          const cols = line.split(',').map(c => c.trim());
          return { email: cols[emailIdx], encrypted_password: cols[passIdx] };
        }).filter(u => u.email);
        setCsvUsers(users);
        setCsvResults(null);
        toast({ title: 'File Loaded', description: `Found ${users.length} users in CSV` });
      } catch (err) {
        toast({ variant: 'destructive', title: 'Parse Error', description: err.message });
      }
    };
    reader.readAsText(file);
    e.target.value = '';
  };

  const importCsvUsers = async () => {
    if (!csvUsers?.length) return;
    setImportingCsv(true);
    setCsvResults(null);
    setError(null);
    try {
      const batchSize = 50;
      const aggregated = { created: 0, skipped: 0, errors: [] };
      for (let i = 0; i < csvUsers.length; i += batchSize) {
        const batch = csvUsers.slice(i, i + batchSize);
        const { data, error: fnErr } = await invokeMigrationFunction({ action: 'import_users_with_passwords', users: batch });
        if (fnErr) throw fnErr;
        if (data?.error) throw new Error(data.error);
        aggregated.created += data.users.created;
        aggregated.skipped += data.users.skipped;
        aggregated.errors = aggregated.errors.concat(data.users.errors || []);
      }
      setCsvResults(aggregated);
      toast({ title: 'Import Complete', description: `Created: ${aggregated.created}, Skipped: ${aggregated.skipped}` });
    } catch (e) {
      setError(e.message);
      toast({ variant: 'destructive', title: 'Import Failed', description: e.message });
    } finally { setImportingCsv(false); }
  };

  const migrateTables = async () => {
    setStep('migrating_tables');
    setError(null);
    setProgress(0);
    setTableResults(null);

    try {
      const tables = [...selectedTables];

      if (tables.length === 0) {
        toast({ title: 'No Tables Selected', description: 'Please select at least one table to migrate.' });
        setStep('scan_done');
        return;
      }

      const aggregatedResults = {};

      // Process one table at a time to avoid timeouts on large tables
      for (let i = 0; i < tables.length; i++) {
        const tableName = tables[i];
        try {
          const { data, error: fnErr } = await invokeMigrationFunction({ action: 'migrate_tables', tables: [tableName] });

          if (fnErr) {
            // Extract meaningful error from edge function response
            const errMsg = typeof fnErr === 'object' ? (fnErr.message || JSON.stringify(fnErr)) : String(fnErr);
            aggregatedResults[tableName] = { inserted: 0, skipped: 0, error: errMsg };
          } else if (data?.error) {
            aggregatedResults[tableName] = { inserted: 0, skipped: 0, error: data.error };
          } else if (data?.results) {
            Object.assign(aggregatedResults, data.results);
          }
        } catch (tableErr) {
          aggregatedResults[tableName] = { inserted: 0, skipped: 0, error: tableErr.message || 'Unknown error' };
        }

        setTableResults({ ...aggregatedResults });
        setProgress(Math.round(((i + 1) / tables.length) * 100));
      }

      const hasErrors = Object.values(aggregatedResults).some(r => r.error);
      setStep('done');
      if (hasErrors) {
        toast({ variant: 'destructive', title: 'Migration Complete with Errors', description: 'Some tables had errors — check the results below.' });
      } else {
        toast({ title: 'Migration Complete', description: 'All table data has been migrated.' });
      }
    } catch (e) {
      setError(e.message);
      setStep('scan_done');
      toast({ variant: 'destructive', title: 'Table Migration Failed', description: e.message });
    }
  };

  const totalSourceRows = tableCounts
    ? Object.values(tableCounts).reduce((sum, c) => sum + Math.max(0, c), 0)
    : 0;

  const tablesWithData = tableCounts
    ? Object.entries(tableCounts).filter(([_, c]) => c > 0)
    : [];

  return (
    <div className="min-h-screen bg-background p-6">
      <div className="mx-auto max-w-4xl space-y-6">
        <div>
          <h1 className="text-3xl font-bold text-foreground">Data Migration</h1>
          <p className="text-muted-foreground mt-1">Import users and table data from your source database</p>
        </div>

        {error && (
          <Card className="border-destructive">
            <CardContent className="pt-4 flex items-center gap-2 text-destructive">
              <AlertTriangle className="h-5 w-5" />
              <span>{error}</span>
            </CardContent>
          </Card>
        )}

        {/* Step 1: Scan */}
        <Card>
          <CardHeader>
            <CardTitle className="flex items-center gap-2">
              <Database className="h-5 w-5" />
              Step 1: Scan Source Database
            </CardTitle>
            <CardDescription>Connect to your source and see what data is available</CardDescription>
          </CardHeader>
          <CardContent>
            <Button onClick={scanSource} disabled={step === 'scanning'}>
              {step === 'scanning' ? <><Loader2 className="h-4 w-4 animate-spin mr-2" /> Scanning...</> : 'Scan Source Database'}
            </Button>

            {tableCounts && (
              <div className="mt-4 space-y-2">
                <div className="flex items-center justify-between">
                  <p className="text-sm font-medium">Found {tablesWithData.length} tables with {totalSourceRows.toLocaleString()} total rows</p>
                  <div className="flex gap-2">
                    <Button variant="ghost" size="sm" className="text-xs h-7" onClick={() => setSelectedTables(new Set(tablesWithData.map(([n]) => n)))}>Select All</Button>
                    <Button variant="ghost" size="sm" className="text-xs h-7" onClick={() => setSelectedTables(new Set())}>Deselect All</Button>
                  </div>
                </div>
                <div className="max-h-60 overflow-y-auto rounded border p-3 space-y-1">
                  {tablesWithData.map(([name, count]) => (
                    <label key={name} className="flex items-center justify-between text-sm cursor-pointer hover:bg-muted/50 rounded px-1 py-0.5">
                      <span className="flex items-center gap-2">
                        <Checkbox
                          checked={selectedTables.has(name)}
                          onCheckedChange={(checked) => {
                            setSelectedTables(prev => {
                              const next = new Set(prev);
                              if (checked) next.add(name); else next.delete(name);
                              return next;
                            });
                          }}
                        />
                        <span className="font-mono text-foreground">{name}</span>
                      </span>
                      <span className="text-muted-foreground">{count.toLocaleString()} rows</span>
                    </label>
                  ))}
                  {tableCounts && Object.entries(tableCounts).filter(([_, c]) => c === -1).length > 0 && (
                    <p className="text-xs text-muted-foreground mt-2">
                      Some tables don't exist in source (will be skipped)
                    </p>
                  )}
                </div>
                <p className="text-xs text-muted-foreground">{selectedTables.size} of {tablesWithData.length} tables selected</p>
              </div>
            )}
          </CardContent>
        </Card>

        {/* Step 2: Migrate Users */}
        {(step === 'scan_done' || step === 'migrating_users' || step === 'done') && (
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                <Users className="h-5 w-5" />
                Step 2: Migrate Users
              </CardTitle>
              <CardDescription>Import user accounts from source or upload a CSV with encrypted passwords</CardDescription>
            </CardHeader>
            <CardContent>
              <Tabs defaultValue="source" className="w-full">
                <TabsList className="mb-4">
                  <TabsTrigger value="source">From Source DB</TabsTrigger>
                  <TabsTrigger value="csv" className="flex items-center gap-1">
                    <KeyRound className="h-3 w-3" /> CSV with Passwords
                  </TabsTrigger>
                </TabsList>

                <TabsContent value="source">
                  <p className="text-sm text-muted-foreground mb-3">Creates accounts with temporary passwords (users will need to reset).</p>
                  <Button onClick={migrateUsers} disabled={step === 'migrating_users'}>
                    {step === 'migrating_users' ? <><Loader2 className="h-4 w-4 animate-spin mr-2" /> Migrating Users...</> : 'Migrate Users'}
                  </Button>
                  {userResults && (
                    <div className="mt-4 space-y-2">
                      <div className="flex gap-4 text-sm">
                        <span className="flex items-center gap-1 text-green-600"><CheckCircle className="h-4 w-4" /> Created: {userResults.created}</span>
                        <span className="flex items-center gap-1 text-muted-foreground">Skipped: {userResults.skipped}</span>
                        {userResults.errors?.length > 0 && (
                          <span className="flex items-center gap-1 text-destructive"><XCircle className="h-4 w-4" /> Errors: {userResults.errors.length}</span>
                        )}
                      </div>
                      {userResults.errors?.length > 0 && (
                        <div className="max-h-40 overflow-y-auto rounded border p-3 text-xs text-destructive space-y-1">
                          {userResults.errors.map((err, i) => <div key={i}>{err}</div>)}
                        </div>
                      )}
                    </div>
                  )}
                </TabsContent>

                <TabsContent value="csv">
                  <div className="space-y-4">
                    <div className="bg-muted/50 border rounded-lg p-4 space-y-2">
                      <p className="text-sm font-medium">Upload a CSV with encrypted (bcrypt) password hashes</p>
                      <p className="text-xs text-muted-foreground">
                        Required columns: <code className="bg-muted px-1 rounded">email</code>, <code className="bg-muted px-1 rounded">encrypted_password</code><br />
                        The encrypted_password should be a bcrypt hash (e.g. <code className="bg-muted px-1 rounded text-[10px]">$2a$10$...</code>).
                        Users will be able to log in with their original passwords.
                      </p>
                    </div>

                    <div className="flex items-center gap-3">
                      <input
                        ref={fileInputRef}
                        type="file"
                        accept=".csv"
                        onChange={handleCsvUpload}
                        className="hidden"
                      />
                      <Button variant="outline" onClick={() => fileInputRef.current?.click()}>
                        <Upload className="h-4 w-4 mr-2" /> Select CSV File
                      </Button>
                      {csvUsers && (
                        <span className="text-sm text-muted-foreground">{csvUsers.length} users loaded</span>
                      )}
                    </div>

                    {csvUsers && (
                      <div className="space-y-3">
                        <div className="max-h-40 overflow-y-auto rounded border p-3 space-y-1">
                          {csvUsers.slice(0, 10).map((u, i) => (
                            <div key={i} className="flex justify-between text-sm">
                              <span className="font-mono text-foreground">{u.email}</span>
                              <span className="text-muted-foreground font-mono text-xs truncate max-w-[200px]">{u.encrypted_password?.slice(0, 20)}...</span>
                            </div>
                          ))}
                          {csvUsers.length > 10 && (
                            <p className="text-xs text-muted-foreground">...and {csvUsers.length - 10} more</p>
                          )}
                        </div>
                        <Button onClick={importCsvUsers} disabled={importingCsv}>
                          {importingCsv ? <><Loader2 className="h-4 w-4 animate-spin mr-2" /> Importing...</> : `Import ${csvUsers.length} Users`}
                        </Button>
                      </div>
                    )}

                    {csvResults && (
                      <div className="mt-4 space-y-2">
                        <div className="flex gap-4 text-sm">
                          <span className="flex items-center gap-1 text-green-600"><CheckCircle className="h-4 w-4" /> Created: {csvResults.created}</span>
                          <span className="flex items-center gap-1 text-muted-foreground">Skipped: {csvResults.skipped}</span>
                          {csvResults.errors?.length > 0 && (
                            <span className="flex items-center gap-1 text-destructive"><XCircle className="h-4 w-4" /> Errors: {csvResults.errors.length}</span>
                          )}
                        </div>
                        {csvResults.errors?.length > 0 && (
                          <div className="max-h-40 overflow-y-auto rounded border p-3 text-xs text-destructive space-y-1">
                            {csvResults.errors.map((err, i) => <div key={i}>{err}</div>)}
                          </div>
                        )}
                      </div>
                    )}
                  </div>
                </TabsContent>
              </Tabs>
            </CardContent>
          </Card>
        )}

        {/* Step 3: Migrate Tables */}
        {(step === 'scan_done' || step === 'migrating_tables' || step === 'done') && (
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                <Database className="h-5 w-5" />
                Step 3: Migrate Table Data
              </CardTitle>
              <CardDescription>Import all rows from source tables (existing records with same IDs will be preserved)</CardDescription>
            </CardHeader>
            <CardContent>
              <Button onClick={migrateTables} disabled={step === 'migrating_tables' || selectedTables.size === 0}>
                {step === 'migrating_tables' ? <><Loader2 className="h-4 w-4 animate-spin mr-2" /> Migrating Data...</> : `Migrate ${selectedTables.size} Selected Table${selectedTables.size !== 1 ? 's' : ''}`}
              </Button>

              {step === 'migrating_tables' && (
                <div className="mt-4">
                  <Progress value={progress} className="h-2" />
                  <p className="text-xs text-muted-foreground mt-1">Processing... this may take several minutes</p>
                </div>
              )}

              {tableResults && (
                <div className="mt-4 max-h-80 overflow-y-auto rounded border p-3 space-y-1">
                  {Object.entries(tableResults).map(([name, result]) => (
                    <div key={name} className="flex justify-between text-sm">
                      <span className="font-mono text-foreground">{name}</span>
                      <span className={result.error ? 'text-destructive' : 'text-muted-foreground'}>
                        {result.error
                          ? `Error: ${result.error}`
                          : `${result.inserted} inserted, ${result.skipped} skipped`}
                      </span>
                    </div>
                  ))}
                </div>
              )}
            </CardContent>
          </Card>
        )}

        {step === 'done' && (
          <Card className="border-green-500">
            <CardContent className="pt-4 flex items-center gap-2 text-green-600">
              <CheckCircle className="h-5 w-5" />
              <span className="font-medium">Migration complete! You may want to send password reset emails to migrated users.</span>
            </CardContent>
          </Card>
        )}
      </div>
    </div>
  );
}
