import {
  PrintProvider,
  ValidationInput,
  ValidationResult,
  QuoteInput,
  CreateOrderInput,
} from './interface.js';
import { PrintQuote, PrintOrder, OrderStatus } from '@book-print/shared';

export interface LuluConfig {
  clientKey: string;
  clientSecret: string;
  environment: 'sandbox' | 'production';
}

export class LuluPrintProvider implements PrintProvider {
  name = 'LuluPrintProvider';
  private baseUrl: string;
  private accessToken: string | null = null;
  private tokenExpiresAt: number = 0;

  constructor(private config: LuluConfig) {
    this.baseUrl =
      config.environment === 'production'
        ? 'https://api.lulu.com'
        : 'https://api.sandbox.lulu.com';
  }

  private async getAuthToken(): Promise<string> {
    if (this.accessToken && Date.now() < this.tokenExpiresAt - 60000) {
      return this.accessToken;
    }

    const credentials = Buffer.from(
      `${this.config.clientKey}:${this.config.clientSecret}`
    ).toString('base64');

    const res = await fetch(`${this.baseUrl}/oauth/token`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        Authorization: `Basic ${credentials}`,
      },
      body: 'grant_type=client_credentials',
    });

    if (!res.ok) {
      const errText = await res.text();
      throw new Error(`Lulu Auth failed: ${res.status} ${errText}`);
    }

    const data: any = await res.json();
    this.accessToken = data.access_token;
    this.tokenExpiresAt = Date.now() + (data.expires_in || 3600) * 1000;
    return this.accessToken!;
  }

  async validateFiles(input: ValidationInput): Promise<ValidationResult> {
    const token = await this.getAuthToken();
    const podPackageId =
      input.binding === 'hardcover'
        ? '0600X0900BWCWHP060UW444MXX' // 6x9 Hardcover Casewrap Matte
        : '0600X0900BWSTDPB060UW444MXX'; // 6x9 Paperback Perfect Bound Gloss

    const res = await fetch(`${this.baseUrl}/print-jobs/validate/`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`,
      },
      body: JSON.stringify({
        line_items: [
          {
            page_count: input.pageCount,
            pod_package_id: podPackageId,
            cover: input.coverPdfUrl,
            interior: input.interiorPdfUrl,
          },
        ],
      }),
    });

    if (!res.ok) {
      const err = await res.json().catch(() => ({}));
      return {
        isValid: false,
        errors: [(err as any).message || `Lulu API validation failed with status ${res.status}`],
        warnings: [],
      };
    }

    return {
      isValid: true,
      errors: [],
      warnings: [],
    };
  }

  async getQuote(input: QuoteInput): Promise<PrintQuote> {
    const token = await this.getAuthToken();
    const podPackageId =
      input.binding === 'hardcover'
        ? '0600X0900BWCWHP060UW444MXX'
        : '0600X0900BWSTDPB060UW444MXX';

    const res = await fetch(`${this.baseUrl}/print-job-cost-calculations/`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`,
      },
      body: JSON.stringify({
        line_items: [
          {
            page_count: input.pageCount,
            pod_package_id: podPackageId,
            quantity: input.quantity,
          },
        ],
        shipping_address: {
          city: input.shippingAddress.city,
          country: input.shippingAddress.country,
          postcode: input.shippingAddress.postalCode,
          state: input.shippingAddress.state,
          street1: input.shippingAddress.addressLine1,
          street2: input.shippingAddress.addressLine2 || '',
        },
      }),
    });

    if (!res.ok) {
      const errText = await res.text();
      throw new Error(`Lulu Quote request failed: ${res.status} ${errText}`);
    }

    const data: any = await res.json();
    const totalMfg = Math.round(parseFloat(data.total_cost_excl_tax || '0') * 100);
    const shippingCost = Math.round(parseFloat(data.shipping_cost?.total_cost_excl_tax || '0') * 100);
    const serviceFee = 400; // $4.00 service fee

    return {
      quoteId: `lulu-quote-${Date.now()}`,
      projectId: input.projectId,
      binding: input.binding,
      quantity: input.quantity,
      manufacturingCostCents: totalMfg,
      selectedShipping: {
        id: data.shipping_option?.level || 'MAIL',
        name: data.shipping_option?.level || 'Standard Mail',
        estimatedDays: '5-7 Days',
        costCents: shippingCost,
        currency: 'USD',
      },
      availableShippingOptions: [
        {
          id: data.shipping_option?.level || 'MAIL',
          name: data.shipping_option?.level || 'Standard Mail',
          estimatedDays: '5-7 Days',
          costCents: shippingCost,
          currency: 'USD',
        },
      ],
      serviceFeeCents: serviceFee,
      totalCostCents: totalMfg + shippingCost + serviceFee,
      currency: 'USD',
      expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
    };
  }

  async createOrder(input: CreateOrderInput): Promise<PrintOrder> {
    const token = await this.getAuthToken();

    const res = await fetch(`${this.baseUrl}/print-jobs/`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`,
        'Cache-Control': 'no-cache',
      },
      body: JSON.stringify({
        external_id: input.projectId,
        line_items: [
          {
            external_id: `item-${input.projectId}`,
            printable_normalization: {
              cover: { url: input.coverPdfUrl },
              interior: { url: input.interiorPdfUrl },
            },
            quantity: 1,
            title: 'Book Print Manuscript',
          },
        ],
        shipping_address: {
          name: input.shippingAddress.fullName,
          street1: input.shippingAddress.addressLine1,
          city: input.shippingAddress.city,
          state: input.shippingAddress.state,
          postcode: input.shippingAddress.postalCode,
          country: input.shippingAddress.country,
        },
      }),
    });

    if (!res.ok) {
      const errText = await res.text();
      throw new Error(`Lulu Order Creation failed: ${res.status} ${errText}`);
    }

    const data: any = await res.json();
    return {
      id: `order-${data.id || Date.now()}`,
      projectId: input.projectId,
      status: 'printer_accepted',
      printerOrderId: String(data.id),
      quote: {
        quoteId: input.quoteId,
        projectId: input.projectId,
        binding: 'paperback',
        quantity: 1,
        manufacturingCostCents: 0,
        selectedShipping: { id: 'MAIL', name: 'Standard', estimatedDays: '5-7', costCents: 0, currency: 'USD' },
        availableShippingOptions: [],
        serviceFeeCents: 400,
        totalCostCents: 0,
        currency: 'USD',
        expiresAt: new Date().toISOString(),
      },
      shippingAddress: input.shippingAddress,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
    };
  }

  async getOrderStatus(orderId: string): Promise<{ status: OrderStatus; trackingNumber?: string; trackingUrl?: string }> {
    const token = await this.getAuthToken();
    const res = await fetch(`${this.baseUrl}/print-jobs/${orderId}/`, {
      headers: { Authorization: `Bearer ${token}` },
    });

    if (!res.ok) {
      throw new Error(`Failed to fetch Lulu order status: ${res.status}`);
    }

    const data: any = await res.json();
    const statusName = data.status?.name?.toLowerCase() || '';
    let status: OrderStatus = 'in_production';
    if (statusName.includes('shipped')) status = 'shipped';
    if (statusName.includes('delivered')) status = 'delivered';

    return {
      status,
      trackingNumber: data.shipping_trace?.tracking_number,
      trackingUrl: data.shipping_trace?.tracking_url,
    };
  }
}
