import React, { useState, useEffect, 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 { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useToast } from '@/hooks/use-toast';
import { Loader2, Plus, Trash2, Table2, Columns3, KeyRound, Save, Upload, Download } from 'lucide-react';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Switch } from '@/components/ui/switch';
import * as XLSX from 'xlsx';

type MappingType = 'table' | 'column' | 'id_value';

interface FieldMapping {
  id?: string;
  mapping_type: MappingType;
  source_table: string;
  destination_table: string;
  source_field: string;
  destination_field: string;
  source_value: string;
  destination_value: string;
  description: string;
  is_active: boolean;
}

const emptyMapping = (type: MappingType): FieldMapping => ({
  mapping_type: type,
  source_table: '',
  destination_table: '',
  source_field: '',
  destination_field: '',
  source_value: '',
  destination_value: '',
  description: '',
  is_active: true,
});

export default function MigrationFieldsPage() {
  const { isAdmin, loading: authLoading } = useAuth();
  const { toast } = useToast();
  const [mappings, setMappings] = useState<FieldMapping[]>([]);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [activeTab, setActiveTab] = useState<MappingType>('table');
  const fileInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    fetchMappings();
  }, []);

  const fetchMappings = async () => {
    setLoading(true);
    const { data, error } = await supabase
      .from('migration_field_mappings')
      .select('*')
      .order('mapping_type')
      .order('source_table');
    if (error) {
      toast({ variant: 'destructive', title: 'Error', description: error.message });
    } else {
      setMappings((data || []) as FieldMapping[]);
    }
    setLoading(false);
  };

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

  const filtered = mappings.filter(m => m.mapping_type === activeTab);

  const addRow = () => {
    setMappings(prev => [...prev, emptyMapping(activeTab)]);
  };

  const updateMapping = (index: number, field: keyof FieldMapping, value: string | boolean) => {
    const globalIndex = mappings.findIndex((m, i) => {
      let count = -1;
      for (let j = 0; j <= i; j++) {
        if (mappings[j].mapping_type === activeTab) count++;
      }
      return count === index;
    });
    if (globalIndex === -1) return;
    setMappings(prev => {
      const copy = [...prev];
      copy[globalIndex] = { ...copy[globalIndex], [field]: value };
      return copy;
    });
  };

  const removeMapping = async (index: number) => {
    const item = filtered[index];
    if (item.id) {
      await supabase.from('migration_field_mappings').delete().eq('id', item.id);
    }
    const globalIndex = mappings.indexOf(item);
    setMappings(prev => prev.filter((_, i) => i !== globalIndex));
    toast({ title: 'Removed', description: 'Mapping deleted.' });
  };

  const saveAll = async () => {
    setSaving(true);
    try {
      for (const m of filtered) {
        const payload = {
          mapping_type: m.mapping_type,
          source_table: m.source_table || null,
          destination_table: m.destination_table || null,
          source_field: m.source_field || null,
          destination_field: m.destination_field || null,
          source_value: m.source_value || null,
          destination_value: m.destination_value || null,
          description: m.description || null,
          is_active: m.is_active,
        };
        if (m.id) {
          const { error } = await supabase.from('migration_field_mappings').update(payload).eq('id', m.id);
          if (error) throw error;
        } else {
          const { data, error } = await supabase.from('migration_field_mappings').insert(payload).select().single();
          if (error) throw error;
          m.id = data.id;
        }
      }
      toast({ title: 'Saved', description: `${filtered.length} mapping(s) saved successfully.` });
      await fetchMappings();
    } catch (e: any) {
      toast({ variant: 'destructive', title: 'Save Failed', description: e.message });
    }
    setSaving(false);
  };

  const handleImportFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    try {
      const data = await file.arrayBuffer();
      const wb = XLSX.read(data);
      const ws = wb.Sheets[wb.SheetNames[0]];
      const rows: any[] = XLSX.utils.sheet_to_json(ws, { defval: '' });

      if (!rows.length) {
        toast({ variant: 'destructive', title: 'Empty file', description: 'No rows found.' });
        return;
      }

      const newMappings: FieldMapping[] = rows.map(row => ({
        mapping_type: 'id_value' as MappingType,
        source_table: String(row.source_table || row.table || ''),
        destination_table: String(row.destination_table || ''),
        source_field: String(row.source_field || row.field || ''),
        destination_field: String(row.destination_field || ''),
        source_value: String(row.source_value || row.source_id || ''),
        destination_value: String(row.destination_value || row.destination_id || ''),
        description: String(row.description || row.notes || ''),
        is_active: true,
      }));

      // Insert all into DB
      const inserts = newMappings.map(m => ({
        mapping_type: m.mapping_type,
        source_table: m.source_table || null,
        destination_table: m.destination_table || null,
        source_field: m.source_field || null,
        destination_field: m.destination_field || null,
        source_value: m.source_value || null,
        destination_value: m.destination_value || null,
        description: m.description || null,
        is_active: m.is_active,
      }));

      const batchSize = 100;
      for (let i = 0; i < inserts.length; i += batchSize) {
        const batch = inserts.slice(i, i + batchSize);
        const { error } = await supabase.from('migration_field_mappings').insert(batch);
        if (error) throw error;
      }

      toast({ title: 'Import Complete', description: `${inserts.length} ID value mapping(s) imported.` });
      await fetchMappings();
    } catch (err: any) {
      toast({ variant: 'destructive', title: 'Import Failed', description: err.message });
    }
    if (fileInputRef.current) fileInputRef.current.value = '';
  };

  const handleDownloadTemplate = async () => {
    const headers = ['source_table', 'source_field', 'source_value', 'destination_value', 'description'];
    const sample = ['associations', 'id', 'old-uuid-here', 'new-uuid-here', 'Acme HOA'];
    const csv = [headers.join(','), sample.join(',')].join('\n');
    const { saveCsv } = await import('@/lib/saveFile');
    await saveCsv(csv, 'id_value_mappings_template.csv');
  };

  return (
    <div className="min-h-screen bg-background p-6">
      <div className="mx-auto max-w-6xl space-y-6">
        <div className="flex items-center justify-between">
          <div>
            <h1 className="text-3xl font-bold text-foreground">Migration Field Mappings</h1>
            <p className="text-muted-foreground mt-1">Map tables, columns, and ID values between source and destination databases</p>
          </div>
          <Button onClick={saveAll} disabled={saving}>
            {saving ? <Loader2 className="h-4 w-4 animate-spin mr-2" /> : <Save className="h-4 w-4 mr-2" />}
            Save All
          </Button>
        </div>

        <Tabs value={activeTab} onValueChange={(v) => setActiveTab(v as MappingType)}>
          <TabsList className="grid w-full grid-cols-3">
            <TabsTrigger value="table" className="flex items-center gap-2">
              <Table2 className="h-4 w-4" /> Table Mappings
            </TabsTrigger>
            <TabsTrigger value="column" className="flex items-center gap-2">
              <Columns3 className="h-4 w-4" /> Column Mappings
            </TabsTrigger>
            <TabsTrigger value="id_value" className="flex items-center gap-2">
              <KeyRound className="h-4 w-4" /> ID Value Mappings
            </TabsTrigger>
          </TabsList>

          <TabsContent value="table" className="space-y-4 mt-4">
            <Card>
              <CardHeader>
                <CardTitle>Table-to-Table Mappings</CardTitle>
                <CardDescription>Map source table names to destination table names when they differ</CardDescription>
              </CardHeader>
              <CardContent className="space-y-3">
                {loading ? (
                  <div className="flex justify-center py-8"><Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /></div>
                ) : (
                  <>
                    <div className="grid grid-cols-[1fr_1fr_1fr_auto_auto] gap-3 text-xs font-semibold text-muted-foreground uppercase tracking-wider px-1">
                      <span>Source Table</span><span>Destination Table</span><span>Description</span><span>Active</span><span />
                    </div>
                    {filtered.map((m, i) => (
                      <div key={m.id || `new-${i}`} className="grid grid-cols-[1fr_1fr_1fr_auto_auto] gap-3 items-center">
                        <Input value={m.source_table} onChange={e => updateMapping(i, 'source_table', e.target.value)} placeholder="e.g. clients" />
                        <Input value={m.destination_table} onChange={e => updateMapping(i, 'destination_table', e.target.value)} placeholder="e.g. associations" />
                        <Input value={m.description} onChange={e => updateMapping(i, 'description', e.target.value)} placeholder="Optional note" />
                        <Switch checked={m.is_active} onCheckedChange={v => updateMapping(i, 'is_active', v)} />
                        <Button variant="ghost" size="icon" onClick={() => removeMapping(i)} className="text-destructive hover:text-destructive">
                          <Trash2 className="h-4 w-4" />
                        </Button>
                      </div>
                    ))}
                    {filtered.length === 0 && <p className="text-sm text-muted-foreground text-center py-4">No table mappings yet. Click "Add Mapping" to start.</p>}
                  </>
                )}
                <Button variant="outline" onClick={addRow} className="w-full mt-2">
                  <Plus className="h-4 w-4 mr-2" /> Add Mapping
                </Button>
              </CardContent>
            </Card>
          </TabsContent>

          <TabsContent value="column" className="space-y-4 mt-4">
            <Card>
              <CardHeader>
                <CardTitle>Column Name Mappings</CardTitle>
                <CardDescription>Map source column names to destination column names (e.g. client_id → association_id)</CardDescription>
              </CardHeader>
              <CardContent className="space-y-3">
                {loading ? (
                  <div className="flex justify-center py-8"><Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /></div>
                ) : (
                  <>
                    <div className="grid grid-cols-[1fr_1fr_1fr_1fr_auto_auto] gap-3 text-xs font-semibold text-muted-foreground uppercase tracking-wider px-1">
                      <span>Table</span><span>Source Column</span><span>Destination Column</span><span>Description</span><span>Active</span><span />
                    </div>
                    {filtered.map((m, i) => (
                      <div key={m.id || `new-${i}`} className="grid grid-cols-[1fr_1fr_1fr_1fr_auto_auto] gap-3 items-center">
                        <Input value={m.source_table} onChange={e => updateMapping(i, 'source_table', e.target.value)} placeholder="e.g. owners" />
                        <Input value={m.source_field} onChange={e => updateMapping(i, 'source_field', e.target.value)} placeholder="e.g. client_id" />
                        <Input value={m.destination_field} onChange={e => updateMapping(i, 'destination_field', e.target.value)} placeholder="e.g. association_id" />
                        <Input value={m.description} onChange={e => updateMapping(i, 'description', e.target.value)} placeholder="Optional note" />
                        <Switch checked={m.is_active} onCheckedChange={v => updateMapping(i, 'is_active', v)} />
                        <Button variant="ghost" size="icon" onClick={() => removeMapping(i)} className="text-destructive hover:text-destructive">
                          <Trash2 className="h-4 w-4" />
                        </Button>
                      </div>
                    ))}
                    {filtered.length === 0 && <p className="text-sm text-muted-foreground text-center py-4">No column mappings yet. Click "Add Mapping" to start.</p>}
                  </>
                )}
                <Button variant="outline" onClick={addRow} className="w-full mt-2">
                  <Plus className="h-4 w-4 mr-2" /> Add Mapping
                </Button>
              </CardContent>
            </Card>
          </TabsContent>

          <TabsContent value="id_value" className="space-y-4 mt-4">
            <Card>
              <CardHeader>
                <div className="flex items-center justify-between">
                  <div>
                    <CardTitle>ID Value Mappings</CardTitle>
                    <CardDescription>Map specific ID values from source to destination (e.g. source UUID → destination UUID)</CardDescription>
                  </div>
                  <div className="flex gap-2">
                    <Button variant="outline" size="sm" onClick={handleDownloadTemplate}>
                      <Download className="h-4 w-4 mr-2" /> Template
                    </Button>
                    <Button variant="outline" size="sm" onClick={() => fileInputRef.current?.click()}>
                      <Upload className="h-4 w-4 mr-2" /> Import CSV/Excel
                    </Button>
                    <input
                      ref={fileInputRef}
                      type="file"
                      accept=".csv,.xlsx,.xls"
                      className="hidden"
                      onChange={handleImportFile}
                    />
                  </div>
                </div>
              </CardHeader>
              <CardContent className="space-y-3">
                {loading ? (
                  <div className="flex justify-center py-8"><Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /></div>
                ) : (
                  <>
                    <div className="grid grid-cols-[0.8fr_1fr_1fr_1fr_auto_auto] gap-3 text-xs font-semibold text-muted-foreground uppercase tracking-wider px-1">
                      <span>Table / Field</span><span>Source Value</span><span>Destination Value</span><span>Description</span><span>Active</span><span />
                    </div>
                    {filtered.map((m, i) => (
                      <div key={m.id || `new-${i}`} className="grid grid-cols-[0.8fr_1fr_1fr_1fr_auto_auto] gap-3 items-center">
                        <div className="space-y-1">
                          <Input value={m.source_table} onChange={e => updateMapping(i, 'source_table', e.target.value)} placeholder="table" className="h-8 text-xs" />
                          <Input value={m.source_field} onChange={e => updateMapping(i, 'source_field', e.target.value)} placeholder="field" className="h-8 text-xs" />
                        </div>
                        <Input value={m.source_value} onChange={e => updateMapping(i, 'source_value', e.target.value)} placeholder="Source ID" className="font-mono text-xs" />
                        <Input value={m.destination_value} onChange={e => updateMapping(i, 'destination_value', e.target.value)} placeholder="Destination ID" className="font-mono text-xs" />
                        <Input value={m.description} onChange={e => updateMapping(i, 'description', e.target.value)} placeholder="e.g. Acme HOA" />
                        <Switch checked={m.is_active} onCheckedChange={v => updateMapping(i, 'is_active', v)} />
                        <Button variant="ghost" size="icon" onClick={() => removeMapping(i)} className="text-destructive hover:text-destructive">
                          <Trash2 className="h-4 w-4" />
                        </Button>
                      </div>
                    ))}
                    {filtered.length === 0 && <p className="text-sm text-muted-foreground text-center py-4">No ID value mappings yet. Click "Add Mapping" to start.</p>}
                  </>
                )}
                <Button variant="outline" onClick={addRow} className="w-full mt-2">
                  <Plus className="h-4 w-4 mr-2" /> Add Mapping
                </Button>
              </CardContent>
            </Card>
          </TabsContent>
        </Tabs>
      </div>
    </div>
  );
}
