import 'dart:math';

import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:krow/core/data/models/shift/event_shift_position_model.dart';
import 'package:krow/core/entity/staff_contact_entity.dart';
import 'package:krow/core/presentation/gen/assets.gen.dart';
import 'package:krow/core/presentation/styles/kw_box_decorations.dart';
import 'package:krow/core/presentation/styles/kw_text_styles.dart';
import 'package:krow/core/presentation/styles/theme.dart';
import 'package:krow/features/invoice/data/models/invoice_item_model.dart';
import 'package:krow/features/invoice/data/models/invoice_model.dart';

import '../../../../../../core/data/models/staff/pivot.dart';
import '../../../../../../core/entity/position_entity.dart';
import '../dialogs/staff_contact_info_popup.dart';

class InvoiceDetailsWidget extends StatefulWidget {
  final InvoiceModel invoice;

  const InvoiceDetailsWidget({super.key, required this.invoice});

  @override
  State<InvoiceDetailsWidget> createState() => _InvoiceDetailsWidgetState();
}

class _InvoiceDetailsWidgetState extends State<InvoiceDetailsWidget> {
  List<ExpandableController> controllers = [];

  ExpandableController showMoreController = ExpandableController();

  Map<EventShiftPositionModel, List<InvoiceItemModel>> staffByPosition = {};

  @override
  void initState() {
    staffByPosition = groupByPosition(widget.invoice.items ?? []);
    controllers =
        List.generate(staffByPosition.length, (_) => ExpandableController());


    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const SizedBox(height: 12),
        Text(
          'Invoice details',
          style: AppTextStyles.headingH3,
        ),
        const SizedBox(height: 12),
        Container(
          decoration: KwBoxDecorations.white12,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              buildTable(),
            ],
          ),
        ),
      ],
    );
  }

  Widget buildTable() {
    final columnWidths = {
      0: const FlexColumnWidth(),
      1: const IntrinsicColumnWidth(),
      2: const IntrinsicColumnWidth(),
      3: const IntrinsicColumnWidth(),
    };

    final rows = <TableRow>[];

    _buildTableHeader(rows);

    var maxVisibleRows = staffByPosition.length;

    for (int index = 0; index < maxVisibleRows; index++) {
      final position = staffByPosition.keys.elementAt(index);
      final group = staffByPosition[position]!;
      final controller = controllers[index];

      final roleDuration =
          group.fold(0.0, (sum, item) => sum + (item.workHours ?? 0));
      final subTotal =
          group.fold(0.0, (sum, item) => sum + (item.totalAmount ?? 0));

      _buildRoleRows(rows, controller, position, roleDuration, subTotal,
          isLastRow: index == maxVisibleRows - 1);

      _buildStaffsRows(controller, group, rows, position);
    }

    return AnimatedSize(
      alignment: Alignment.topCenter,
      duration: Duration(milliseconds: 500),
      curve: Curves.easeInOut,
      child: Table(
        columnWidths: columnWidths,
        defaultVerticalAlignment: TableCellVerticalAlignment.middle,
        children: rows,
      ),
    );
  }

  void _buildTableHeader(List<TableRow> rows) {
    return rows.add(
      TableRow(
        children: buildRowCells(
          [
            Padding(
              padding: const EdgeInsets.only(left: 22, top: 12, bottom: 12),
              child: Text('Role', style: AppTextStyles.bodyMediumMed),
            ),
            Padding(
              padding: const EdgeInsets.only(
                  left: 8, right: 16, top: 12, bottom: 12),
              child: Text('Rate (\$/h)', style: AppTextStyles.bodyMediumMed),
            ),
            Padding(
              padding: const EdgeInsets.only(
                  left: 8, right: 16, top: 12, bottom: 12),
              child: Text('Hours', style: AppTextStyles.bodyMediumMed),
            ),
            Padding(
              padding:
                  const EdgeInsets.only(left: 8, right: 8, top: 12, bottom: 12),
              child: Text('Subtotal', style: AppTextStyles.bodyMediumMed),
            ),
          ],
        ),
      ),
    );
  }

  void _buildRoleRows(List<TableRow> rows, ExpandableController controller,
      EventShiftPositionModel position, double roleDuration, double subTotal,
      {required bool isLastRow}) {
    return rows.add(
      TableRow(
        children: buildRowCells(
          isLastRow: isLastRow && !controller.expanded,
          [
            expandableCell(
              controller: controller,
              padding: const EdgeInsets.only(left: 6, top: 16, bottom: 13),
              child: Row(
                children: [
                  AnimatedRotation(
                    duration: Duration(milliseconds: 300),
                    turns: controller.expanded ? -0.5 : 0,
                    child: Assets.images.icons.chevronDown
                        .svg(width: 12, height: 12),
                  ),
                  Gap(4),
                  Expanded(
                      child: Text(
                    position.businessSkill.skill?.name ?? '',
                    overflow: TextOverflow.ellipsis,
                  )),
                ],
              ),
            ),
            expandableCell(
              controller: controller,
              padding: const EdgeInsets.only(
                  left: 12, right: 8, top: 16, bottom: 16),
              child: Text(
                '\$${position.rate.toStringAsFixed(2)}/h',
                style: AppTextStyles.bodyMediumReg,
              ),
            ),
            expandableCell(
              controller: controller,
              padding: const EdgeInsets.only(
                  left: 12, right: 8, top: 16, bottom: 16),
              child: Text(roleDuration.toStringAsFixed(1),
                  style: AppTextStyles.bodyMediumReg),
            ),
            expandableCell(
              controller: controller,
              padding: const EdgeInsets.only(
                  left: 12, right: 8, top: 16, bottom: 16),
              child: Text('\$${subTotal.toStringAsFixed(2)}',
                  style: AppTextStyles.bodyMediumReg),
            ),
          ],
        ),
      ),
    );
  }

  void _buildStaffsRows(
      ExpandableController controller,
      List<InvoiceItemModel> group,
      List<TableRow> rows,
      EventShiftPositionModel position) {
    if (controller.expanded) {
      for (int i = 0; i < group.length; i++) {
        final user = group[i];
        rows.add(
          TableRow(
            children: buildRowCells(isLastRow: i == group.length - 1, [
              GestureDetector(
                onTap: () {
                  StaffInvoiceContactInfoPopup.show(
                      context,
                      makeStaffContact(
                        user,
                        position,
                      ),
                      date: widget.invoice.event?.date,
                      hours: user.workHours ?? 0.0,
                      subtotal: user.totalAmount ?? 0.0);
                },
                child: buildAnimatedStaffCell(
                  visible: controller.expanded,
                  child: Padding(
                    padding: const EdgeInsets.only(left: 12.0),
                    child: Text(
                      '${user.staff?.firstName ?? ''} ${user.staff?.lastName ?? ''}',
                      style: AppTextStyles.bodyTinyReg.copyWith(
                        color: AppColors.blackGray,
                      ),
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                ),
              ),
              buildAnimatedStaffCell(
                visible: controller.expanded,
                child: Text('\$${(user.rate?.toStringAsFixed(2)) ?? 0}/h',
                    style: AppTextStyles.bodyTinyReg),
              ),
              buildAnimatedStaffCell(
                visible: controller.expanded,
                child: Text('${user.workHours?.toStringAsFixed(1) ?? 0}',
                    style: AppTextStyles.bodyTinyReg),
              ),
              buildAnimatedStaffCell(
                visible: controller.expanded,
                child: Text('\$${user.totalAmount ?? 0}',
                    style: AppTextStyles.bodyTinyReg),
              ),
            ]),
          ),
        );
      }
    }
  }

  List<Widget> buildRowCells(List<Widget> cells, {bool isLastRow = false}) {
    return List.generate(cells.length, (i) {
      final isLastColumn = i == cells.length - 1;
      return buildGridCell(
        child: cells[i],
        showRight: !isLastColumn,
        showBottom: !isLastRow,
      );
    });
  }

  Widget expandableCell(
      {required Widget child,
      required ExpandableController controller,
      required EdgeInsets padding}) {
    return GestureDetector(
        onTap: () {
          setState(() {
            controller.expanded = !controller.expanded;
          });
        },
        child: Container(
            color: Colors.transparent, padding: padding, child: child));
  }

  Widget buildGridCell({
    required Widget child,
    bool showRight = true,
    bool showBottom = true,
    EdgeInsets padding = const EdgeInsets.all(8),
  }) {
    return Container(
      padding: padding,
      decoration: BoxDecoration(
        border: Border(
          right: showRight
              ? BorderSide(color: Colors.grey.shade300, width: 1)
              : BorderSide.none,
          bottom: showBottom
              ? BorderSide(color: Colors.grey.shade300, width: 1)
              : BorderSide.none,
        ),
      ),
      child: child,
    );
  }

  Widget buildAnimatedStaffCell({
    required bool visible,
    required Widget child,
    Duration duration = const Duration(milliseconds: 300),
    Curve curve = Curves.easeInOut,
  }) {
    return AnimatedContainer(
      duration: duration,
      curve: curve,
      color: Colors.transparent,
      height: visible ? null : 0,
      child: Padding(
        padding: const EdgeInsets.only(left: 10, right: 6, top: 10, bottom: 10),
        child: AnimatedOpacity(
          duration: duration,
          opacity: visible ? 1 : 0,
          child: visible ? child : IgnorePointer(child: child),
        ),
      ),
    );
  }

  Map<EventShiftPositionModel, List<InvoiceItemModel>> groupByPosition(
    List<InvoiceItemModel> items,
  ) {

    final Map<String, EventShiftPositionModel> positionCache = {};
    final Map<EventShiftPositionModel, List<InvoiceItemModel>> grouped = {};

    for (final item in items) {
      final position = item.position;

      if (position == null) continue;

      final id = position.businessSkill.id ?? '';

      final existingPosition = positionCache[id];

      final key = existingPosition ??
          () {
            positionCache[id] = position;
            return position;
          }();

      grouped.putIfAbsent(key, () => []);
      grouped[key]!.add(item);
    }
    return grouped;
  }

  StaffContact makeStaffContact(
      InvoiceItemModel user, EventShiftPositionModel position) {
    var staff = user.staff!;
    var pivot = user.position!.staff!
        .firstWhere(
          (element) => element.id == user.staff?.id,
        )
        .pivot;

    return StaffContact(
      id: staff.id ?? '',
      photoUrl: staff.avatar ?? '',
      firstName: staff.firstName ?? '',
      lastName: staff.lastName ?? '',
      phoneNumber: staff.phone ?? '',
      email: staff.email ?? '',
      rate: position.businessSkill.price ?? 0,
      status: pivot?.status ?? PivotStatus.assigned,
      startAt: pivot?.clockIn ?? '',
      endAt: pivot?.clockOut ?? '',
      breakIn: pivot?.breakIn ?? '',
      breakOut: pivot?.breakOut ?? '',
      parentPosition: PositionEntity.fromDto(
          position,
          DateTime.tryParse(widget.invoice.event?.date ?? '') ??
              DateTime.now()),
      skillName: position.businessSkill.skill?.name ?? '',
    );
  }
}
