// app/api/staff/facturation/route.ts
import { NextResponse } from "next/server";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";

export const dynamic = 'force-dynamic';
export const revalidate = 0;
export const runtime = 'nodejs';

// Lazily import AWS SDK pieces to avoid client bundle impact
async function getS3Presigner() {
  const [{ S3Client, GetObjectCommand }, { getSignedUrl }] = await Promise.all([
    import("@aws-sdk/client-s3"),
    import("@aws-sdk/s3-request-presigner"),
  ]);
  return { S3Client, GetObjectCommand, getSignedUrl };
}

function mapStatus(input?: string | null, row?: any):
  | "payee"
  | "annulee"
  | "prete"
  | "emise"
  | "en_cours"
  | string {
  if (!input && row) {
    if (row?.payment_date) return "payee";
    return "emise";
  }
  const s = String(input || "").trim().toLowerCase();
  if (!s) return "emise";
  if (/(payée|payee|paid)/i.test(s)) return "payee";
  if (/(annulée|annulee|cancell|cancel)/i.test(s)) return "annulee";
  if (/(prête|prepar|ready|prete)/i.test(s)) return "prete";
  if (/(en\s*cours|pending|due)/i.test(s)) return "en_cours";
  if (/(émise|emise|issued)/i.test(s)) return "emise";
  return s;
}

async function isStaffUser(supabase: any, userId: string): Promise<boolean> {
  try {
    const { data: staffRow } = await supabase
      .from('staff_users')
      .select('is_staff')
      .eq('user_id', userId)
      .maybeSingle();
    return !!staffRow?.is_staff;
  } catch {
    return false;
  }
}

// GET - Lister toutes les factures (staff uniquement)
export async function GET(req: Request) {
  try {
    const url = new URL(req.url);
    const page = Math.max(1, parseInt(url.searchParams.get('page') || '1', 10));
    const limit = Math.max(1, Math.min(50, parseInt(url.searchParams.get('limit') || '25', 10)));
    const from = (page - 1) * limit;
    const to = from + limit - 1;

    const supabase = createRouteHandlerClient({ cookies });
    const { data: { session } } = await supabase.auth.getSession();
    if (!session) return NextResponse.json({ error: 'unauthorized' }, { status: 401 });

    // Vérifier que l'utilisateur est staff
    const isStaff = await isStaffUser(supabase, session.user.id);
    if (!isStaff) {
      return NextResponse.json({ error: 'forbidden', message: 'Staff access required' }, { status: 403 });
    }

    // Récupérer toutes les factures avec les infos d'organisation (même méthode que l'API client)
    let query: any = supabase.from('invoices').select('*', { count: 'exact' });
    // Pas de filtre org_id pour le staff - on veut toutes les factures
    query = query.order('invoice_date', { ascending: false, nullsFirst: false }).order('created_at', { ascending: false }).range(from, to);

    const { data, error, count } = await query;
    if (error) {
      console.error('[api/staff/facturation] invoices error:', error.message);
      return NextResponse.json({ error: 'supabase_error', detail: error.message }, { status: 500 });
    }

    // Récupérer les noms des organisations pour chaque facture
    const orgIds = [...new Set((data || []).map((invoice: any) => invoice.org_id).filter(Boolean))];
    let organizationsMap: { [key: string]: string } = {};
    
    if (orgIds.length > 0) {
      const { data: orgsData } = await supabase
        .from('organizations')
        .select('id, structure_api')
        .in('id', orgIds);
      
      if (orgsData) {
        organizationsMap = orgsData.reduce((acc: any, org: any) => {
          acc[org.id] = org.structure_api;
          return acc;
        }, {});
      }
    }

    // Presign S3 URLs for PDFs (même méthode que l'API client)
    let signer: any = null;
    const bucket = (process.env.AWS_S3_BUCKET || 'odentas-docs').trim();
    const region = process.env.AWS_REGION || 'eu-west-3';
    const expireSeconds = Math.max(60, Math.min(60 * 60, Number(process.env.INVOICE_URL_EXPIRES ?? 900)));

    const maybeSign = async (key?: string | null) => {
      if (!key) return null;
      try {
        if (!signer) {
          const { S3Client, GetObjectCommand, getSignedUrl } = await getS3Presigner();
          signer = { S3Client, GetObjectCommand, getSignedUrl, client: new S3Client({ region }) };
        }
        const cmd = new signer.GetObjectCommand({ Bucket: bucket, Key: key });
        const url = await signer.getSignedUrl(signer.client, cmd, { expiresIn: expireSeconds });
        return url as string;
      } catch (e) {
        console.error('[api/staff/facturation] presign error for key', key, e);
        return null;
      }
    };

    const items = await Promise.all((data || []).map(async (r: any) => ({
      id: r.id as string,
      numero: (r.invoice_number ?? null) as string | null,
      periode: (r.period_label ?? null) as string | null,
      date: (r.invoice_date ?? null) as string | null,
      montant_ht: (typeof r.amount_ht === 'number' ? r.amount_ht : parseFloat(r.amount_ht || '0')) || 0,
      montant_ttc: (typeof r.amount_ttc === 'number' ? r.amount_ttc : parseFloat(r.amount_ttc || '0')) || 0,
      statut: mapStatus(r.status, r),
      pdf: await maybeSign(r.pdf_s3_key || null),
      org_id: r.org_id,
      organization_name: organizationsMap[r.org_id] || null,
      notified: r.notified || false,
    })));

    const total = typeof count === 'number' ? count : items.length;
    const hasMore = from + items.length < total;

    return NextResponse.json({
      factures: { items, page, limit, hasMore },
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    return NextResponse.json({ error: 'internal_server_error', message }, { status: 500 });
  }
}

// POST - Créer une nouvelle facture (staff uniquement)
export async function POST(req: Request) {
  try {
    const supabase = createRouteHandlerClient({ cookies });
    const { data: { session } } = await supabase.auth.getSession();
    if (!session) return NextResponse.json({ error: 'unauthorized' }, { status: 401 });

    // Vérifier que l'utilisateur est staff
    const isStaff = await isStaffUser(supabase, session.user.id);
    if (!isStaff) {
      return NextResponse.json({ error: 'forbidden', message: 'Staff access required' }, { status: 403 });
    }

    const body = await req.json();
    const {
      org_id,
      numero,
      periode,
      date,
      montant_ht,
      montant_ttc,
      statut,
      notes,
      pdf_s3_key
    } = body;

    // Validation basique
    if (!org_id || !montant_ttc) {
      return NextResponse.json({ error: 'validation_error', message: 'org_id and montant_ttc are required' }, { status: 400 });
    }

    // Créer la facture
    const { data: newInvoice, error } = await supabase
      .from('invoices')
      .insert({
        org_id,
        invoice_number: numero || null,
        period_label: periode || null,
        invoice_date: date || null,
        amount_ht: parseFloat(montant_ht) || 0,
        amount_ttc: parseFloat(montant_ttc),
        status: statut || 'emise',
        notes: notes || null,
        pdf_s3_key: pdf_s3_key || null,
        created_at: new Date().toISOString(),
        updated_at: new Date().toISOString(),
      })
      .select()
      .single();

    if (error) {
      console.error('[api/staff/facturation] create error:', error.message);
      return NextResponse.json({ error: 'supabase_error', detail: error.message }, { status: 500 });
    }

    return NextResponse.json({
      id: newInvoice.id,
      message: 'Invoice created successfully'
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    return NextResponse.json({ error: 'internal_server_error', message }, { status: 500 });
  }
}