// Migration utility to transfer localStorage data to Firebase Firestore
import { Timestamp } from 'firebase/firestore';
import {
  shopService,
  customerService,
  customerMeasurementService,
  inventoryService,
  tailoringItemService,
  employeeService,
  orderService,
  incomeTransactionService,
  expenseTransactionService,
  appearanceSettingsService,
  notificationSettingsService,
} from './service';
import {
  getMockOrders,
  getMockCustomers,
  getMockMeasurements,
  getMockInventory,
  getMockTailoringItems,
  getMockEmployees,
  getMockIncome,
  getOtherExpenses,
  getShopProfile,
  getAppearanceSettings,
  getNotificationSettings,
} from '../data';
import type {
  Order,
  Customer,
  CustomerMeasurement,
  InventoryItem,
  TailoringItem,
  Employee,
  Transaction,
  Expense,
  ShopProfile,
  AppearanceSettings,
  NotificationSettings,
} from '../data';
import type {
  ShopProfileDB,
  CustomerDB,
  CustomerMeasurementDB,
  InventoryItemDB,
  TailoringItemDB,
  EmployeeDB,
  OrderDB,
  IncomeTransactionDB,
  ExpenseTransactionDB,
  AppearanceSettingsDB,
  NotificationSettingsDB,
} from './types';

export interface MigrationResult {
  success: boolean;
  message: string;
  details?: {
    shops: number;
    customers: number;
    measurements: number;
    inventory: number;
    tailoringItems: number;
    employees: number;
    orders: number;
    incomeTransactions: number;
    expenseTransactions: number;
    settings: number;
  };
  errors?: string[];
}

export class DataMigration {
  private shopId: string;
  private userId: string;
  private errors: string[] = [];

  constructor(shopId: string, userId: string) {
    this.shopId = shopId;
    this.userId = userId;
  }

  // Main migration function
  async migrateAllData(): Promise<MigrationResult> {
    console.log('Starting data migration from localStorage to Firebase...');
    this.errors = [];

    try {
      const results = {
        shops: 0,
        customers: 0,
        measurements: 0,
        inventory: 0,
        tailoringItems: 0,
        employees: 0,
        orders: 0,
        incomeTransactions: 0,
        expenseTransactions: 0,
        settings: 0,
      };

      // Migrate shop profile
      results.shops = await this.migrateShopProfile();
      
      // Migrate customers
      results.customers = await this.migrateCustomers();
      
      // Migrate customer measurements
      results.measurements = await this.migrateCustomerMeasurements();
      
      // Migrate inventory
      results.inventory = await this.migrateInventory();
      
      // Migrate tailoring items
      results.tailoringItems = await this.migrateTailoringItems();
      
      // Migrate employees
      results.employees = await this.migrateEmployees();
      
      // Migrate orders
      results.orders = await this.migrateOrders();
      
      // Migrate income transactions
      results.incomeTransactions = await this.migrateIncomeTransactions();
      
      // Migrate expense transactions
      results.expenseTransactions = await this.migrateExpenseTransactions();
      
      // Migrate settings
      results.settings = await this.migrateSettings();

      const totalMigrated = Object.values(results).reduce((sum, count) => sum + count, 0);
      
      return {
        success: this.errors.length === 0,
        message: this.errors.length === 0 
          ? `Successfully migrated ${totalMigrated} records to Firebase`
          : `Migration completed with ${this.errors.length} errors. ${totalMigrated} records migrated.`,
        details: results,
        errors: this.errors.length > 0 ? this.errors : undefined,
      };
    } catch (error: any) {
      console.error('Migration failed:', error);
      return {
        success: false,
        message: `Migration failed: ${error.message}`,
        errors: [...this.errors, error.message],
      };
    }
  }

  // Migrate shop profile
  private async migrateShopProfile(): Promise<number> {
    try {
      const shopProfile = getShopProfile();
      
      const shopData: Omit<ShopProfileDB, 'id' | 'createdAt' | 'updatedAt'> = {
        shopName: shopProfile.shopName,
        email: shopProfile.email,
        address: shopProfile.address,
        contact: shopProfile.contact,
        logoUrl: shopProfile.logoUrl,
        ownerId: this.userId,
      };

      // Use the provided shopId instead of generating a new one
      const result = await shopService.create(shopData);
      
      if (!result.success) {
        this.errors.push(`Failed to migrate shop profile: ${result.error}`);
        return 0;
      }
      
      return 1;
    } catch (error: any) {
      this.errors.push(`Error migrating shop profile: ${error.message}`);
      return 0;
    }
  }

  // Migrate customers
  private async migrateCustomers(): Promise<number> {
    try {
      const customers = getMockCustomers();
      let migratedCount = 0;

      for (const customer of customers) {
        const customerData: Omit<CustomerDB, 'id' | 'createdAt' | 'updatedAt'> = {
          name: customer.name,
          phone: customer.phone,
          shopId: this.shopId,
          totalOrders: 0,
          totalSpent: 0,
        };

        const result = await customerService.create(customerData);
        
        if (result.success) {
          migratedCount++;
        } else {
          this.errors.push(`Failed to migrate customer ${customer.name}: ${result.error}`);
        }
      }

      return migratedCount;
    } catch (error: any) {
      this.errors.push(`Error migrating customers: ${error.message}`);
      return 0;
    }
  }

  // Migrate customer measurements
  private async migrateCustomerMeasurements(): Promise<number> {
    try {
      const measurements = getMockMeasurements();
      let migratedCount = 0;

      for (const measurement of measurements) {
        const measurementData: Omit<CustomerMeasurementDB, 'id' | 'createdAt' | 'updatedAt'> = {
          customerId: measurement.customerId,
          itemName: measurement.itemName,
          measurements: measurement.measurements,
          shopId: this.shopId,
        };

        const result = await customerMeasurementService.create(measurementData);
        
        if (result.success) {
          migratedCount++;
        } else {
          this.errors.push(`Failed to migrate measurement for ${measurement.itemName}: ${result.error}`);
        }
      }

      return migratedCount;
    } catch (error: any) {
      this.errors.push(`Error migrating measurements: ${error.message}`);
      return 0;
    }
  }

  // Migrate inventory
  private async migrateInventory(): Promise<number> {
    try {
      const inventory = getMockInventory();
      let migratedCount = 0;

      for (const item of inventory) {
        const inventoryData: Omit<InventoryItemDB, 'id' | 'createdAt' | 'updatedAt'> = {
          name: item.name,
          type: item.type,
          color: item.color,
          pricePerMeter: item.pricePerMeter,
          quantity: item.quantity,
          lowStockThreshold: item.lowStockThreshold,
          shopId: this.shopId,
        };

        const result = await inventoryService.create(inventoryData);
        
        if (result.success) {
          migratedCount++;
        } else {
          this.errors.push(`Failed to migrate inventory item ${item.name}: ${result.error}`);
        }
      }

      return migratedCount;
    } catch (error: any) {
      this.errors.push(`Error migrating inventory: ${error.message}`);
      return 0;
    }
  }

  // Migrate tailoring items
  private async migrateTailoringItems(): Promise<number> {
    try {
      const items = getMockTailoringItems();
      let migratedCount = 0;

      for (const item of items) {
        const itemData: Omit<TailoringItemDB, 'id' | 'createdAt' | 'updatedAt'> = {
          name: item.name,
          category: item.category,
          sewingPrice: item.sewingPrice,
          artisanWage: item.artisanWage,
          shopId: this.shopId,
          isActive: true,
        };

        const result = await tailoringItemService.create(itemData);
        
        if (result.success) {
          migratedCount++;
        } else {
          this.errors.push(`Failed to migrate tailoring item ${item.name}: ${result.error}`);
        }
      }

      return migratedCount;
    } catch (error: any) {
      this.errors.push(`Error migrating tailoring items: ${error.message}`);
      return 0;
    }
  }

  // Migrate employees
  private async migrateEmployees(): Promise<number> {
    try {
      const employees = getMockEmployees();
      let migratedCount = 0;

      for (const employee of employees) {
        const employeeData: Omit<EmployeeDB, 'id' | 'createdAt' | 'updatedAt'> = {
          name: employee.name,
          phone: employee.phone,
          role: employee.role,
          monthlySalary: employee.monthlySalary,
          shopId: this.shopId,
          hireDate: Timestamp.now(), // Default to current date
          isActive: true,
        };

        const result = await employeeService.create(employeeData);
        
        if (result.success) {
          migratedCount++;
        } else {
          this.errors.push(`Failed to migrate employee ${employee.name}: ${result.error}`);
        }
      }

      return migratedCount;
    } catch (error: any) {
      this.errors.push(`Error migrating employees: ${error.message}`);
      return 0;
    }
  }

  // Migrate orders
  private async migrateOrders(): Promise<number> {
    try {
      const orders = getMockOrders();
      let migratedCount = 0;

      for (const order of orders) {
        const orderData: Omit<OrderDB, 'id' | 'createdAt' | 'updatedAt'> = {
          memoId: order.memoId,
          customerId: order.customerId,
          customerName: order.customer,
          customerPhone: order.phone,
          type: order.type,
          status: order.status,
          orderDate: Timestamp.fromDate(new Date(order.date)),
          totalAmount: order.totalAmount,
          paidAmount: order.paidAmount,
          totalArtisanWage: order.totalArtisanWage,
          items: order.items.map(item => ({
            id: item.id,
            name: item.name,
            quantity: item.quantity,
            price: item.price,
            artisanWage: item.artisanWage,
            measurements: item.measurements,
          })),
          deliveryDate: order.deliveryDate ? Timestamp.fromDate(new Date(order.deliveryDate)) : undefined,
          artisanName: order.artisan,
          cuttingMasterName: order.cuttingMaster,
          artisanAssignedDate: order.artisanAssignedDate ? Timestamp.fromDate(new Date(order.artisanAssignedDate)) : undefined,
          artisanCompletedDate: order.artisanCompletedDate ? Timestamp.fromDate(new Date(order.artisanCompletedDate)) : undefined,
          cuttingCompletedDate: order.cuttingCompletedDate ? Timestamp.fromDate(new Date(order.cuttingCompletedDate)) : undefined,
          shopId: this.shopId,
          priority: 'medium',
        };

        const result = await orderService.create(orderData);
        
        if (result.success) {
          migratedCount++;
        } else {
          this.errors.push(`Failed to migrate order ${order.id}: ${result.error}`);
        }
      }

      return migratedCount;
    } catch (error: any) {
      this.errors.push(`Error migrating orders: ${error.message}`);
      return 0;
    }
  }

  // Migrate income transactions
  private async migrateIncomeTransactions(): Promise<number> {
    try {
      const transactions = getMockIncome();
      let migratedCount = 0;

      for (const transaction of transactions) {
        const transactionData: Omit<IncomeTransactionDB, 'id' | 'createdAt' | 'updatedAt'> = {
          category: transaction.category,
          amount: transaction.amount,
          description: transaction.description,
          transactionDate: Timestamp.fromDate(new Date(transaction.date)),
          shopId: this.shopId,
          paymentMethod: 'cash', // Default payment method
          isEditable: transaction.isEditable ?? true,
        };

        const result = await incomeTransactionService.create(transactionData);
        
        if (result.success) {
          migratedCount++;
        } else {
          this.errors.push(`Failed to migrate income transaction: ${result.error}`);
        }
      }

      return migratedCount;
    } catch (error: any) {
      this.errors.push(`Error migrating income transactions: ${error.message}`);
      return 0;
    }
  }

  // Migrate expense transactions
  private async migrateExpenseTransactions(): Promise<number> {
    try {
      const expenses = getOtherExpenses();
      let migratedCount = 0;

      for (const expense of expenses) {
        const expenseData: Omit<ExpenseTransactionDB, 'id' | 'createdAt' | 'updatedAt'> = {
          category: expense.category,
          amount: expense.amount,
          description: expense.description,
          person: expense.person,
          transactionDate: Timestamp.fromDate(new Date(expense.date)),
          shopId: this.shopId,
          paymentMethod: 'cash', // Default payment method
          isEditable: expense.isEditable ?? true,
        };

        const result = await expenseTransactionService.create(expenseData);
        
        if (result.success) {
          migratedCount++;
        } else {
          this.errors.push(`Failed to migrate expense transaction: ${result.error}`);
        }
      }

      return migratedCount;
    } catch (error: any) {
      this.errors.push(`Error migrating expense transactions: ${error.message}`);
      return 0;
    }
  }

  // Migrate settings
  private async migrateSettings(): Promise<number> {
    try {
      let migratedCount = 0;

      // Migrate appearance settings
      const appearanceSettings = getAppearanceSettings();
      const appearanceData: Omit<AppearanceSettingsDB, 'id' | 'createdAt' | 'updatedAt'> = {
        theme: appearanceSettings.theme,
        font: appearanceSettings.font,
        shopId: this.shopId,
      };

      const appearanceResult = await appearanceSettingsService.create(appearanceData);
      if (appearanceResult.success) {
        migratedCount++;
      } else {
        this.errors.push(`Failed to migrate appearance settings: ${appearanceResult.error}`);
      }

      // Migrate notification settings
      const notificationSettings = getNotificationSettings();
      const notificationData: Omit<NotificationSettingsDB, 'id' | 'createdAt' | 'updatedAt'> = {
        smsEnabled: notificationSettings.smsEnabled,
        smsProvider: notificationSettings.smsProvider,
        smsApiKey: notificationSettings.smsApiKey,
        smsApiSecret: notificationSettings.smsApiSecret,
        smsSenderId: notificationSettings.smsSenderId,
        smsMessageTemplate: notificationSettings.smsMessageTemplate,
        whatsappEnabled: notificationSettings.whatsappEnabled,
        whatsappApiKey: notificationSettings.whatsappApiKey,
        whatsappSenderNumber: notificationSettings.whatsappSenderNumber,
        whatsappMessageTemplate: notificationSettings.whatsappMessageTemplate,
        shopId: this.shopId,
      };

      const notificationResult = await notificationSettingsService.create(notificationData);
      if (notificationResult.success) {
        migratedCount++;
      } else {
        this.errors.push(`Failed to migrate notification settings: ${notificationResult.error}`);
      }

      return migratedCount;
    } catch (error: any) {
      this.errors.push(`Error migrating settings: ${error.message}`);
      return 0;
    }
  }

  // Check if migration is needed
  static async checkMigrationNeeded(): Promise<boolean> {
    if (typeof window === 'undefined') return false;
    
    // Check if there's any localStorage data
    const hasOrders = localStorage.getItem('mockOrders');
    const hasCustomers = localStorage.getItem('mockCustomers');
    const hasInventory = localStorage.getItem('mockInventory');
    const hasEmployees = localStorage.getItem('mockEmployees');
    
    return !!(hasOrders || hasCustomers || hasInventory || hasEmployees);
  }

  // Clear localStorage after successful migration
  static clearLocalStorageData(): void {
    if (typeof window === 'undefined') return;
    
    const keysToRemove = [
      'mockOrders',
      'mockCustomers',
      'mockMeasurements',
      'mockInventory',
      'mockTailoringItems',
      'mockEmployees',
      'mockIncome',
      'mockOtherExpenses',
      'shopProfile',
      'appearanceSettings',
      'notificationSettings',
      'loginCredentials',
      'mockServices',
    ];
    
    keysToRemove.forEach(key => {
      localStorage.removeItem(key);
    });
    
    console.log('LocalStorage data cleared after successful migration');
  }
}

// Utility function to run migration
export async function runMigration(shopId: string, userId: string): Promise<MigrationResult> {
  const migration = new DataMigration(shopId, userId);
  return migration.migrateAllData();
}

// Utility function to check and run migration if needed
export async function checkAndRunMigration(shopId: string, userId: string): Promise<MigrationResult | null> {
  const migrationNeeded = await DataMigration.checkMigrationNeeded();
  
  if (!migrationNeeded) {
    return null;
  }
  
  console.log('Migration needed, starting data transfer...');
  const result = await runMigration(shopId, userId);
  
  if (result.success) {
    DataMigration.clearLocalStorageData();
  }
  
  return result;
}
