import 'package:excel/excel.dart';
import 'package:intl/intl.dart';
import '../models/panen_model.dart';
import 'excel_save_helper.dart';

class ExcelExportService {
  static Future<String> exportWeeklyReport({
    required List<Panen> panens,
    required DateTime startDate,
    required DateTime endDate,
    required String kandangFilter,
  }) async {
    try {
      print('[ExcelExportService] Starting export...');

      final bytes = _generateExcelContent(
        panens,
        startDate,
        endDate,
        kandangFilter,
      );

      final now = DateTime.now();
      final fileName = 'Laporan_Telur_${_formatDate(now)}.xlsx';

      final savedLocation = await saveReportFile(
        fileName: fileName,
        bytes: bytes,
        mimeType:
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      );

      print('[ExcelExportService] Export completed successfully');
      return savedLocation;
    } catch (e, stackTrace) {
      print('[ExcelExportService] ERROR: $e');
      print('[ExcelExportService] Stack trace: $stackTrace');
      throw Exception('Error creating report: $e');
    }
  }

  static String _formatDate(DateTime date) {
    final day = date.day.toString().padLeft(2, '0');
    final month = date.month.toString().padLeft(2, '0');
    final year = date.year;
    return '$day-$month-$year';
  }

  static List<int> _generateExcelContent(
    List<Panen> panens,
    DateTime startDate,
    DateTime endDate,
    String kandangFilter,
  ) {
    final excel = Excel.createExcel();
    const sheetName = 'Laporan';
    final defaultSheet = excel.getDefaultSheet();
    if (defaultSheet != null && defaultSheet != sheetName) {
      excel.rename(defaultSheet, sheetName);
    }
    final sheet = excel[sheetName];

    final boldStyle = CellStyle(bold: true);

    CellIndex idx(int row, int col) =>
        CellIndex.indexByColumnRow(columnIndex: col, rowIndex: row);

    void writeText(int row, int col, String value, {bool bold = false}) {
      sheet.updateCell(
        idx(row, col),
        TextCellValue(value),
        cellStyle: bold ? boldStyle : null,
      );
    }

    void writeInt(int row, int col, int value, {bool bold = false}) {
      sheet.updateCell(
        idx(row, col),
        IntCellValue(value),
        cellStyle: bold ? boldStyle : null,
      );
    }

    int totalKandang1Pagi = 0;
    int totalKandang1Sore = 0;
    int totalKandang2Pagi = 0;
    int totalKandang2Sore = 0;
    int totalOverall = 0;
    final perHari = <DateTime, _DailyReport>{};

    for (final panen in panens) {
      final dateKey = DateTime(
        panen.tanggalPanen.year,
        panen.tanggalPanen.month,
        panen.tanggalPanen.day,
      );

      final daily = perHari.putIfAbsent(dateKey, () => _DailyReport());
      final jumlah = panen.jumlahTelur;
      final normalized = _normalizeKandang(panen.kandangId, panen.kandangNama);
      final jenis = _normalizeJenisPanen(panen);

      if (normalized.contains('kandang1')) {
        if (jenis == 'pagi') {
          totalKandang1Pagi += jumlah;
          daily.kandang1Pagi += jumlah;
        } else if (jenis == 'sore') {
          totalKandang1Sore += jumlah;
          daily.kandang1Sore += jumlah;
        }
      } else if (normalized.contains('kandang2')) {
        if (jenis == 'pagi') {
          totalKandang2Pagi += jumlah;
          daily.kandang2Pagi += jumlah;
        } else if (jenis == 'sore') {
          totalKandang2Sore += jumlah;
          daily.kandang2Sore += jumlah;
        }
      }

      totalOverall += jumlah;
      daily.total += jumlah;
    }

    final periodText =
        '${DateFormat('dd/MM/yyyy').format(startDate)} - ${DateFormat('dd/MM/yyyy').format(endDate)}';
    final filterText =
        kandangFilter == 'semua' ? 'Semua Kandang' : kandangFilter;

    writeText(0, 0, 'LAPORAN PRODUKSI TELUR', bold: true);
    writeText(1, 0, 'Periode', bold: true);
    writeText(1, 1, periodText);
    writeText(2, 0, 'Filter Kandang', bold: true);
    writeText(2, 1, filterText);

    final totalKandang1 = totalKandang1Pagi + totalKandang1Sore;
    final totalKandang2 = totalKandang2Pagi + totalKandang2Sore;

    writeText(4, 0, 'Jumlah total telur kandang 1 (pagi)', bold: true);
    writeInt(4, 1, totalKandang1Pagi, bold: true);
    writeText(5, 0, 'Jumlah total telur kandang 1 (sore)', bold: true);
    writeInt(5, 1, totalKandang1Sore, bold: true);
    writeText(6, 0, 'Jumlah total telur kandang 1', bold: true);
    writeInt(6, 1, totalKandang1, bold: true);

    writeText(8, 0, 'Jumlah total telur kandang 2 (pagi)', bold: true);
    writeInt(8, 1, totalKandang2Pagi, bold: true);
    writeText(9, 0, 'Jumlah total telur kandang 2 (sore)', bold: true);
    writeInt(9, 1, totalKandang2Sore, bold: true);
    writeText(10, 0, 'Jumlah total telur kandang 2', bold: true);
    writeInt(10, 1, totalKandang2, bold: true);

    writeText(12, 0, 'Total keseluruhan', bold: true);
    writeInt(12, 1, totalOverall, bold: true);

    writeText(14, 0, 'Tanggal', bold: true);
    writeText(14, 1, 'Kandang 1 Pagi', bold: true);
    writeText(14, 2, 'Kandang 1 Sore', bold: true);
    writeText(14, 3, 'Kandang 2 Pagi', bold: true);
    writeText(14, 4, 'Kandang 2 Sore', bold: true);
    writeText(14, 5, 'Total Telur Per Hari', bold: true);

    final sortedDates = perHari.keys.toList()..sort((a, b) => a.compareTo(b));
    var row = 15;
    for (final date in sortedDates) {
      final daily = perHari[date]!;
      writeText(row, 0, DateFormat('dd/MM/yyyy').format(date));
      writeInt(row, 1, daily.kandang1Pagi);
      writeInt(row, 2, daily.kandang1Sore);
      writeInt(row, 3, daily.kandang2Pagi);
      writeInt(row, 4, daily.kandang2Sore);
      writeInt(row, 5, daily.total);
      row++;
    }

    final encoded = excel.encode();
    if (encoded == null) {
      throw Exception('Gagal membuat file Excel');
    }

    return encoded;
  }

  static String _normalizeKandang(String kandangId, String kandangNama) {
    return '${kandangId.toLowerCase()} ${kandangNama.toLowerCase()}'
        .replaceAll('_', '')
        .replaceAll(' ', '');
  }

  static String _normalizeJenisPanen(Panen panen) {
    final explicit = (panen.jenisPanen ?? '').trim().toLowerCase();
    if (explicit == 'pagi' || explicit == 'sore') {
      return explicit;
    }

    final match = RegExp(r'^(\d{1,2})[:.]').firstMatch(panen.jam.trim());
    final hour = match != null ? int.tryParse(match.group(1)!) : null;
    if (hour != null) {
      return hour < 12 ? 'pagi' : 'sore';
    }

    return 'sore';
  }
}

class _DailyReport {
  int kandang1Pagi = 0;
  int kandang1Sore = 0;
  int kandang2Pagi = 0;
  int kandang2Sore = 0;
  int total = 0;
}
