import db from '../../config/database';
import { v4 as uuidv4 } from 'uuid';
import { logger } from '../../utils/logger';

interface Bill {
  id: string;
  tenantId: string;
  shopId: string;
  type: 'FEATURE' | 'SUBSCRIPTION' | 'USAGE';
  amount: number;
  currency: string;
  status: 'PENDING' | 'PAID' | 'FAILED';
  relatedId?: string;
  traceId?: string;
  taskId?: string;
  businessType?: 'TOC' | 'TOB';
  createdAt: Date;
  updatedAt: Date;
}

interface BillResult {
  bill: Bill;
  success: boolean;
}

export class BillingService {
  private static readonly TABLE = 'cf_bill';

  static async initTable(): Promise<void> {
    const hasTable = await db.schema.hasTable(this.TABLE);
    if (!hasTable) {
      await db.schema.createTable(this.TABLE, (table) => {
        table.string('id', 64).primary();
        table.string('tenantId', 64).notNullable();
        table.string('shopId', 64).notNullable();
        table.enum('type', ['FEATURE', 'SUBSCRIPTION', 'USAGE']).notNullable();
        table.decimal('amount', 10, 2).notNullable();
        table.string('currency', 10).notNullable();
        table.enum('status', ['PENDING', 'PAID', 'FAILED']).notNullable();
        table.string('relatedId', 64);
        table.string('traceId', 64);
        table.string('taskId', 64);
        table.enum('businessType', ['TOC', 'TOB']);
        table.timestamp('createdAt').notNullable();
        table.timestamp('updatedAt').notNullable();
        
        table.index(['tenantId', 'shopId']);
        table.index(['status']);
      });
      logger.info('[BillingService] Table cf_bill created');
    }
  }

  static async createBill(billData: Partial<Bill>): Promise<BillResult> {
    const id = uuidv4();
    
    try {
      await db(this.TABLE).insert({
        id,
        ...billData,
        status: billData.status || 'PENDING',
        createdAt: new Date(),
        updatedAt: new Date()
      });
      
      const bill = (await this.getBillById(id))!;
      return {
        bill,
        success: true
      };
    } catch (error) {
      logger.error('[BillingService] Error creating bill', { error, billData });
      return {
        bill: {} as Bill,
        success: false
      };
    }
  }

  static async getBillById(id: string): Promise<Bill | null> {
    return await db(this.TABLE).where({ id }).first();
  }

  static async updateBillStatus(id: string, status: Bill['status']): Promise<Bill | null> {
    await db(this.TABLE)
      .where({ id })
      .update({
        status,
        updatedAt: new Date()
      });
    
    return await this.getBillById(id);
  }

  static async listBills(tenantId: string, filters?: any): Promise<Bill[]> {
    let query = db(this.TABLE).where({ tenantId });
    
    if (filters) {
      if (filters.status) query = query.where({ status: filters.status });
      if (filters.type) query = query.where({ type: filters.type });
      if (filters.startDate) query = query.where('createdAt', '>=', filters.startDate);
      if (filters.endDate) query = query.where('createdAt', '<=', filters.endDate);
    }
    
    return await query.orderBy('createdAt', 'desc');
  }
}
