import { http } from './http';
import {
  Warehouse,
  WarehouseSku,
  WarehouseStock,
  SalesSku,
  SkuMapping,
  StockMovement,
  StockReservation,
  InventoryAlert,
  StockAvailability,
  OrderFulfillmentPlan,
  MappingType,
} from '@/types/warehouse';

export interface IWarehouseDataSource {
  fetchWarehouses(tenantId: string): Promise<Warehouse[]>;
  fetchWarehouseSkuList(warehouseId: string): Promise<WarehouseSku[]>;
  fetchStockList(warehouseId: string): Promise<WarehouseStock[]>;
  fetchSalesSkuList(tenantId: string, shopId?: string): Promise<SalesSku[]>;
  fetchSkuMappings(tenantId: string): Promise<SkuMapping[]>;
  createSkuMapping(mapping: Partial<SkuMapping>): Promise<SkuMapping>;
  updateSkuMapping(mappingId: string, updates: Partial<SkuMapping>): Promise<SkuMapping>;
  deleteSkuMapping(mappingId: string): Promise<void>;
  checkStockAvailability(salesSkuCode: string, quantity: number): Promise<StockAvailability>;
  reserveStock(orderId: string, items: { salesSkuCode: string; quantity: number }[]): Promise<StockReservation[]>;
  releaseStock(reservationId: string): Promise<void>;
  fulfillOrder(orderId: string): Promise<OrderFulfillmentPlan>;
  adjustStock(warehouseSkuId: string, quantity: number, reason: string): Promise<StockMovement>;
  fetchStockMovements(warehouseId: string, filters?: any): Promise<StockMovement[]>;
  fetchInventoryAlerts(tenantId: string): Promise<InventoryAlert[]>;
}

const WAREHOUSE_TYPES = {
  SELF: '自营仓库',
  THIRD_PARTY: '第三方仓库',
  VIRTUAL: '虚拟仓库',
};

const MAPPING_TYPE_NAMES: Record<MappingType, string> = {
  ONE_TO_ONE: '一对一',
  ONE_TO_MANY: '一对多',
  COMBO: '组合商品',
  BUNDLE: '套装商品',
};

class MockWarehouseDataSource implements IWarehouseDataSource {
  private warehouses: Warehouse[] = [];
  private warehouseSkus: WarehouseSku[] = [];
  private stocks: WarehouseStock[] = [];
  private salesSkus: SalesSku[] = [];
  private skuMappings: SkuMapping[] = [];
  private movements: StockMovement[] = [];
  private reservations: StockReservation[] = [];
  private alerts: InventoryAlert[] = [];

  constructor() {
    this.initMockData();
  }

  private initMockData() {
    this.warehouses = [
      {
        id: 'WH-001',
        tenant_id: 'tenant-001',
        name: '深圳主仓',
        code: 'SZ-MAIN',
        type: 'SELF',
        address: '深圳市宝安区XX路XX号',
        contact_person: '张三',
        contact_phone: '13800138000',
        capacity: 10000,
        used_capacity: 6500,
        status: 'ACTIVE',
        priority: 1,
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
      {
        id: 'WH-002',
        tenant_id: 'tenant-001',
        name: '广州分仓',
        code: 'GZ-BRANCH',
        type: 'SELF',
        address: '广州市白云区XX路XX号',
        contact_person: '李四',
        contact_phone: '13900139000',
        capacity: 5000,
        used_capacity: 2000,
        status: 'ACTIVE',
        priority: 2,
        created_at: '2026-01-15T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
    ];

    this.warehouseSkus = [
      {
        id: 'WSKU-001',
        warehouse_id: 'WH-001',
        sku_code: 'WH-PHONE-CASE-001',
        sku_name: '手机壳-通用款',
        barcode: '6901234567890',
        category: '手机配件',
        specifications: { color: '黑色', material: 'TPU' },
        unit: '个',
        weight_kg: 0.05,
        volume_m3: 0.0001,
        shelf_location: 'A-01-01',
        safety_stock: 100,
        max_stock: 1000,
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
      {
        id: 'WSKU-002',
        warehouse_id: 'WH-001',
        sku_code: 'WH-SCREEN-PROTECTOR-001',
        sku_name: '钢化膜-通用款',
        barcode: '6901234567891',
        category: '手机配件',
        specifications: { type: '钢化膜', size: '通用' },
        unit: '片',
        weight_kg: 0.02,
        volume_m3: 0.00005,
        shelf_location: 'A-01-02',
        safety_stock: 200,
        max_stock: 2000,
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
    ];

    this.stocks = [
      {
        id: 'STK-001',
        warehouse_id: 'WH-001',
        warehouse_sku_id: 'WSKU-001',
        sku_code: 'WH-PHONE-CASE-001',
        quantity: 500,
        available_quantity: 450,
        reserved_quantity: 50,
        damaged_quantity: 0,
        in_transit_quantity: 0,
        status: 'AVAILABLE',
        last_inbound_at: '2026-03-20T10:00:00Z',
        last_outbound_at: '2026-03-23T15:00:00Z',
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
      {
        id: 'STK-002',
        warehouse_id: 'WH-001',
        warehouse_sku_id: 'WSKU-002',
        sku_code: 'WH-SCREEN-PROTECTOR-001',
        quantity: 800,
        available_quantity: 750,
        reserved_quantity: 50,
        damaged_quantity: 0,
        in_transit_quantity: 0,
        status: 'AVAILABLE',
        last_inbound_at: '2026-03-19T10:00:00Z',
        last_outbound_at: '2026-03-22T15:00:00Z',
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
    ];

    this.salesSkus = [
      {
        id: 'SSKU-001',
        tenant_id: 'tenant-001',
        shop_id: 'shop-001',
        sku_code: 'SALES-PHONE-CASE-RED',
        sku_name: '红色手机壳',
        product_id: 'PROD-001',
        product_name: '时尚手机壳',
        platform: 'Shopify',
        price: 19.99,
        cost_price: 5.00,
        status: 'ACTIVE',
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
      {
        id: 'SSKU-002',
        tenant_id: 'tenant-001',
        shop_id: 'shop-001',
        sku_code: 'SALES-PHONE-CASE-BLUE',
        sku_name: '蓝色手机壳',
        product_id: 'PROD-001',
        product_name: '时尚手机壳',
        platform: 'Shopify',
        price: 19.99,
        cost_price: 5.00,
        status: 'ACTIVE',
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
      {
        id: 'SSKU-003',
        tenant_id: 'tenant-001',
        shop_id: 'shop-001',
        sku_code: 'SALES-BUNDLE-001',
        sku_name: '手机壳+膜套装',
        product_id: 'PROD-002',
        product_name: '手机配件套装',
        platform: 'Shopify',
        price: 29.99,
        cost_price: 7.00,
        status: 'ACTIVE',
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
    ];

    this.skuMappings = [
      {
        id: 'MAP-001',
        tenant_id: 'tenant-001',
        sales_sku_id: 'SSKU-001',
        sales_sku_code: 'SALES-PHONE-CASE-RED',
        mapping_type: 'ONE_TO_ONE',
        warehouse_items: [
          {
            warehouse_sku_id: 'WSKU-001',
            warehouse_sku_code: 'WH-PHONE-CASE-001',
            quantity: 1,
            warehouse_id: 'WH-001',
          },
        ],
        is_active: true,
        priority: 1,
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
      {
        id: 'MAP-002',
        tenant_id: 'tenant-001',
        sales_sku_id: 'SSKU-002',
        sales_sku_code: 'SALES-PHONE-CASE-BLUE',
        mapping_type: 'ONE_TO_ONE',
        warehouse_items: [
          {
            warehouse_sku_id: 'WSKU-001',
            warehouse_sku_code: 'WH-PHONE-CASE-001',
            quantity: 1,
            warehouse_id: 'WH-001',
          },
        ],
        is_active: true,
        priority: 1,
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
      {
        id: 'MAP-003',
        tenant_id: 'tenant-001',
        sales_sku_id: 'SSKU-003',
        sales_sku_code: 'SALES-BUNDLE-001',
        mapping_type: 'COMBO',
        warehouse_items: [
          {
            warehouse_sku_id: 'WSKU-001',
            warehouse_sku_code: 'WH-PHONE-CASE-001',
            quantity: 1,
            warehouse_id: 'WH-001',
          },
          {
            warehouse_sku_id: 'WSKU-002',
            warehouse_sku_code: 'WH-SCREEN-PROTECTOR-001',
            quantity: 1,
            warehouse_id: 'WH-001',
          },
        ],
        is_active: true,
        priority: 1,
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-03-24T00:00:00Z',
      },
    ];
  }

  async fetchWarehouses(tenantId: string): Promise<Warehouse[]> {
    await this.delay(300);
    return this.warehouses.filter(w => w.tenant_id === tenantId);
  }

  async fetchWarehouseSkuList(warehouseId: string): Promise<WarehouseSku[]> {
    await this.delay(300);
    return this.warehouseSkus.filter(s => s.warehouse_id === warehouseId);
  }

  async fetchStockList(warehouseId: string): Promise<WarehouseStock[]> {
    await this.delay(300);
    return this.stocks.filter(s => s.warehouse_id === warehouseId);
  }

  async fetchSalesSkuList(tenantId: string, shopId?: string): Promise<SalesSku[]> {
    await this.delay(300);
    return this.salesSkus.filter(s => 
      s.tenant_id === tenantId && 
      (!shopId || s.shop_id === shopId)
    );
  }

  async fetchSkuMappings(tenantId: string): Promise<SkuMapping[]> {
    await this.delay(300);
    return this.skuMappings.filter(m => m.tenant_id === tenantId);
  }

  async createSkuMapping(mapping: Partial<SkuMapping>): Promise<SkuMapping> {
    await this.delay(300);
    const newMapping: SkuMapping = {
      id: `MAP-${Date.now()}`,
      tenant_id: mapping.tenant_id || 'tenant-001',
      sales_sku_id: mapping.sales_sku_id || '',
      sales_sku_code: mapping.sales_sku_code || '',
      mapping_type: mapping.mapping_type || 'ONE_TO_ONE',
      warehouse_items: mapping.warehouse_items || [],
      is_active: mapping.is_active ?? true,
      priority: mapping.priority || 1,
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
    };
    this.skuMappings.push(newMapping);
    return newMapping;
  }

  async updateSkuMapping(mappingId: string, updates: Partial<SkuMapping>): Promise<SkuMapping> {
    await this.delay(300);
    const index = this.skuMappings.findIndex(m => m.id === mappingId);
    if (index === -1) {
      throw new Error('Mapping not found');
    }
    this.skuMappings[index] = {
      ...this.skuMappings[index],
      ...updates,
      updated_at: new Date().toISOString(),
    };
    return this.skuMappings[index];
  }

  async deleteSkuMapping(mappingId: string): Promise<void> {
    await this.delay(300);
    const index = this.skuMappings.findIndex(m => m.id === mappingId);
    if (index !== -1) {
      this.skuMappings.splice(index, 1);
    }
  }

  async checkStockAvailability(salesSkuCode: string, quantity: number): Promise<StockAvailability> {
    await this.delay(300);
    
    const mapping = this.skuMappings.find(m => 
      m.sales_sku_code === salesSkuCode && m.is_active
    );
    
    if (!mapping) {
      return {
        sales_sku_code: salesSkuCode,
        total_available: 0,
        total_reserved: 0,
        total_in_transit: 0,
        warehouse_breakdown: [],
        can_fulfill: false,
      };
    }

    const warehouseBreakdown = mapping.warehouse_items.map(item => {
      const stock = this.stocks.find(s => 
        s.warehouse_sku_id === item.warehouse_sku_id
      );
      const warehouse = this.warehouses.find(w => w.id === item.warehouse_id);
      
      return {
        warehouse_id: item.warehouse_id,
        warehouse_name: warehouse?.name || '',
        available: stock ? Math.floor(stock.available_quantity / item.quantity) : 0,
        reserved: stock ? Math.floor(stock.reserved_quantity / item.quantity) : 0,
      };
    });

    const totalAvailable = Math.min(...warehouseBreakdown.map(w => w.available));
    const totalReserved = Math.max(...warehouseBreakdown.map(w => w.reserved));

    return {
      sales_sku_code: salesSkuCode,
      total_available: totalAvailable,
      total_reserved: totalReserved,
      total_in_transit: 0,
      warehouse_breakdown: warehouseBreakdown,
      can_fulfill: totalAvailable >= quantity,
    };
  }

  async reserveStock(
    orderId: string, 
    items: { salesSkuCode: string; quantity: number }[]
  ): Promise<StockReservation[]> {
    await this.delay(500);
    
    const reservations: StockReservation[] = [];
    
    for (const item of items) {
      const mapping = this.skuMappings.find(m => 
        m.sales_sku_code === item.salesSkuCode && m.is_active
      );
      
      if (!mapping) continue;

      for (const whItem of mapping.warehouse_items) {
        const reserveQty = whItem.quantity * item.quantity;
        const stock = this.stocks.find(s => s.warehouse_sku_id === whItem.warehouse_sku_id);
        
        if (stock && stock.available_quantity >= reserveQty) {
          stock.available_quantity -= reserveQty;
          stock.reserved_quantity += reserveQty;
          
          const reservation: StockReservation = {
            id: `RES-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
            tenant_id: 'tenant-001',
            warehouse_id: whItem.warehouse_id,
            warehouse_sku_id: whItem.warehouse_sku_id,
            sku_code: whItem.warehouse_sku_code,
            order_id: orderId,
            order_item_id: `${orderId}-${item.salesSkuCode}`,
            sales_sku_code: item.salesSkuCode,
            quantity: reserveQty,
            status: 'CONFIRMED',
            reserved_at: new Date().toISOString(),
            expires_at: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
            created_at: new Date().toISOString(),
            updated_at: new Date().toISOString(),
          };
          
          reservations.push(reservation);
          this.reservations.push(reservation);
        }
      }
    }
    
    return reservations;
  }

  async releaseStock(reservationId: string): Promise<void> {
    await this.delay(300);
    
    const reservation = this.reservations.find(r => r.id === reservationId);
    if (!reservation) return;

    const stock = this.stocks.find(s => s.warehouse_sku_id === reservation.warehouse_sku_id);
    if (stock) {
      stock.reserved_quantity -= reservation.quantity;
      stock.available_quantity += reservation.quantity;
    }

    reservation.status = 'RELEASED';
    reservation.released_at = new Date().toISOString();
  }

  async fulfillOrder(orderId: string): Promise<OrderFulfillmentPlan> {
    await this.delay(500);
    
    const orderReservations = this.reservations.filter(r => 
      r.order_id === orderId && r.status === 'CONFIRMED'
    );

    const items = this.groupReservationsBySalesSku(orderReservations);

    return {
      order_id: orderId,
      items,
      total_warehouses: new Set(orderReservations.map(r => r.warehouse_id)).size,
      estimated_ship_date: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
      fulfillment_strategy: items.length > 1 ? 'MULTI_WAREHOUSE' : 'SINGLE_WAREHOUSE',
    };
  }

  private groupReservationsBySalesSku(reservations: StockReservation[]): any[] {
    const grouped = new Map<string, any>();
    
    for (const res of reservations) {
      if (!grouped.has(res.sales_sku_code)) {
        grouped.set(res.sales_sku_code, {
          order_item_id: res.order_item_id,
          sales_sku_code: res.sales_sku_code,
          quantity: 0,
          warehouse_allocations: [],
        });
      }
      
      const item = grouped.get(res.sales_sku_code);
      item.quantity += res.quantity;
      
      const warehouse = this.warehouses.find(w => w.id === res.warehouse_id);
      const whSku = this.warehouseSkus.find(s => s.id === res.warehouse_sku_id);
      
      item.warehouse_allocations.push({
        warehouse_id: res.warehouse_id,
        warehouse_name: warehouse?.name || '',
        warehouse_sku_code: res.sku_code,
        quantity: res.quantity,
        shelf_location: whSku?.shelf_location || '',
      });
    }
    
    return Array.from(grouped.values());
  }

  async adjustStock(
    warehouseSkuId: string, 
    quantity: number, 
    reason: string
  ): Promise<StockMovement> {
    await this.delay(300);
    
    const stock = this.stocks.find(s => s.warehouse_sku_id === warehouseSkuId);
    if (!stock) {
      throw new Error('Stock not found');
    }

    const beforeQuantity = stock.quantity;
    stock.quantity += quantity;
    stock.available_quantity += quantity;

    const movement: StockMovement = {
      id: `MV-${Date.now()}`,
      tenant_id: 'tenant-001',
      warehouse_id: stock.warehouse_id,
      warehouse_sku_id: warehouseSkuId,
      sku_code: stock.sku_code,
      movement_type: quantity > 0 ? 'INBOUND' : 'OUTBOUND',
      quantity: Math.abs(quantity),
      before_quantity: beforeQuantity,
      after_quantity: stock.quantity,
      reference_type: 'ADJUSTMENT',
      operator: 'admin',
      remark: reason,
      created_at: new Date().toISOString(),
    };

    this.movements.unshift(movement);
    return movement;
  }

  async fetchStockMovements(warehouseId: string, filters?: any): Promise<StockMovement[]> {
    await this.delay(300);
    return this.movements.filter(m => m.warehouse_id === warehouseId);
  }

  async fetchInventoryAlerts(tenantId: string): Promise<InventoryAlert[]> {
    await this.delay(300);
    
    const alerts: InventoryAlert[] = [];
    
    for (const stock of this.stocks) {
      const whSku = this.warehouseSkus.find(s => s.id === stock.warehouse_sku_id);
      if (!whSku) continue;

      if (stock.available_quantity < whSku.safety_stock) {
        alerts.push({
          id: `ALERT-${Date.now()}-${stock.id}`,
          tenant_id: tenantId,
          warehouse_id: stock.warehouse_id,
          warehouse_sku_id: stock.warehouse_sku_id,
          sku_code: stock.sku_code,
          alert_type: stock.available_quantity === 0 ? 'OUT_OF_STOCK' : 'LOW_STOCK',
          current_quantity: stock.available_quantity,
          threshold: whSku.safety_stock,
          message: `库存不足: ${whSku.sku_name} 当前库存 ${stock.available_quantity}，安全库存 ${whSku.safety_stock}`,
          status: 'ACTIVE',
          created_at: new Date().toISOString(),
        });
      }
    }
    
    return alerts;
  }

  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

class ApiWarehouseDataSource implements IWarehouseDataSource {
  private baseUrl = '/api/v1/warehouse';

  async fetchWarehouses(tenantId: string): Promise<Warehouse[]> {
    const response = await http.get(`${this.baseUrl}/warehouses?tenant_id=${tenantId}`);
    return response.data;
  }

  async fetchWarehouseSkuList(warehouseId: string): Promise<WarehouseSku[]> {
    const response = await http.get(`${this.baseUrl}/skus?warehouse_id=${warehouseId}`);
    return response.data;
  }

  async fetchStockList(warehouseId: string): Promise<WarehouseStock[]> {
    const response = await http.get(`${this.baseUrl}/stocks?warehouse_id=${warehouseId}`);
    return response.data;
  }

  async fetchSalesSkuList(tenantId: string, shopId?: string): Promise<SalesSku[]> {
    const params = new URLSearchParams({ tenant_id: tenantId });
    if (shopId) params.append('shop_id', shopId);
    const response = await http.get(`${this.baseUrl}/sales-skus?${params}`);
    return response.data;
  }

  async fetchSkuMappings(tenantId: string): Promise<SkuMapping[]> {
    const response = await http.get(`${this.baseUrl}/sku-mappings?tenant_id=${tenantId}`);
    return response.data;
  }

  async createSkuMapping(mapping: Partial<SkuMapping>): Promise<SkuMapping> {
    const response = await http.post(`${this.baseUrl}/sku-mappings`, mapping);
    return response.data;
  }

  async updateSkuMapping(mappingId: string, updates: Partial<SkuMapping>): Promise<SkuMapping> {
    const response = await http.put(`${this.baseUrl}/sku-mappings/${mappingId}`, updates);
    return response.data;
  }

  async deleteSkuMapping(mappingId: string): Promise<void> {
    await http.delete(`${this.baseUrl}/sku-mappings/${mappingId}`);
  }

  async checkStockAvailability(salesSkuCode: string, quantity: number): Promise<StockAvailability> {
    const response = await http.get(`${this.baseUrl}/stock-availability`, {
      params: { sales_sku_code: salesSkuCode, quantity },
    });
    return response.data;
  }

  async reserveStock(
    orderId: string, 
    items: { salesSkuCode: string; quantity: number }[]
  ): Promise<StockReservation[]> {
    const response = await http.post(`${this.baseUrl}/stock-reservations`, {
      order_id: orderId,
      items,
    });
    return response.data;
  }

  async releaseStock(reservationId: string): Promise<void> {
    await http.delete(`${this.baseUrl}/stock-reservations/${reservationId}`);
  }

  async fulfillOrder(orderId: string): Promise<OrderFulfillmentPlan> {
    const response = await http.post(`${this.baseUrl}/order-fulfillment`, {
      order_id: orderId,
    });
    return response.data;
  }

  async adjustStock(
    warehouseSkuId: string, 
    quantity: number, 
    reason: string
  ): Promise<StockMovement> {
    const response = await http.post(`${this.baseUrl}/stock-adjustments`, {
      warehouse_sku_id: warehouseSkuId,
      quantity,
      reason,
    });
    return response.data;
  }

  async fetchStockMovements(warehouseId: string, filters?: any): Promise<StockMovement[]> {
    const response = await http.get(`${this.baseUrl}/stock-movements`, {
      params: { warehouse_id: warehouseId, ...filters },
    });
    return response.data;
  }

  async fetchInventoryAlerts(tenantId: string): Promise<InventoryAlert[]> {
    const response = await http.get(`${this.baseUrl}/inventory-alerts?tenant_id=${tenantId}`);
    return response.data;
  }
}

const useMock = process.env.NODE_ENV === 'development' || process.env.REACT_APP_USE_MOCK === 'true';
export const warehouseDataSource: IWarehouseDataSource = useMock
  ? new MockWarehouseDataSource()
  : new ApiWarehouseDataSource();

export { WAREHOUSE_TYPES, MAPPING_TYPE_NAMES };
