import 'dart:async';

import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart' as intl;
import 'package:shadcn_ui/shadcn_ui.dart';

import 'package:superport_v2/core/constants/app_sections.dart';
import 'package:superport_v2/widgets/app_layout.dart';
import 'package:superport_v2/widgets/components/filter_bar.dart';
import 'package:superport_v2/widgets/components/superport_pagination_controls.dart';
import 'package:superport_v2/widgets/components/superport_table.dart';
import 'package:superport_v2/widgets/components/responsive_section.dart';

import '../../../../../core/config/environment.dart';
import '../../../../../widgets/spec_page.dart';
import '../../../uom/domain/entities/uom.dart';
import '../../../uom/domain/repositories/uom_repository.dart';
import '../../../vendor/domain/entities/vendor.dart';
import '../../../vendor/domain/repositories/vendor_repository.dart';
import '../../domain/entities/product.dart';
import '../../domain/repositories/product_repository.dart';
import '../controllers/product_controller.dart';
import '../dialogs/product_detail_dialog.dart';

/// 제품 관리 페이지. 기능 플래그에 따라 사양/실제 화면을 전환한다.
class ProductPage extends StatelessWidget {
  const ProductPage({super.key, required this.routeUri});

  final Uri routeUri;

  @override
  Widget build(BuildContext context) {
    final enabled = Environment.flag('FEATURE_PRODUCTS_ENABLED');
    if (!enabled) {
      return const SpecPage(
        title: '장비 모델(제품) 관리',
        summary: '제품 코드, 제조사, 단위 정보를 유지하여 재고 라인과 연계합니다.',
        sections: [
          SpecSection(
            title: '입력 폼',
            items: [
              '제품코드 [Text]',
              '제품명 [Text]',
              '제조사 [Dropdown]',
              '단위 [Dropdown]',
              '사용여부 [Switch]',
              '비고 [Text]',
            ],
          ),
          SpecSection(
            title: '수정 폼',
            items: ['제품코드 [ReadOnly]', '생성일시 [ReadOnly]'],
          ),
          SpecSection(
            title: '테이블 리스트',
            description: '1행 예시',
            table: SpecTable(
              columns: ['번호', '제품코드', '제품명', '제조사', '단위', '사용여부', '비고', '변경일시'],
              rows: [
                [
                  '1',
                  'P-100',
                  'XR-5000',
                  '슈퍼벤더',
                  'EA',
                  'Y',
                  '-',
                  '2024-03-01 10:00',
                ],
              ],
            ),
          ),
        ],
      );
    }

    return _ProductEnabledPage(routeUri: routeUri);
  }
}

/// 제품 기능이 활성화된 경우 사용하는 실제 화면 위젯.
class _ProductEnabledPage extends StatefulWidget {
  const _ProductEnabledPage({required this.routeUri});

  final Uri routeUri;

  @override
  State<_ProductEnabledPage> createState() => _ProductEnabledPageState();
}

/// 제품 목록과 필터/폼 상태를 관리하는 상태 클래스.
class _ProductEnabledPageState extends State<_ProductEnabledPage> {
  late final ProductController _controller;
  final TextEditingController _searchController = TextEditingController();
  final FocusNode _searchFocus = FocusNode();
  final intl.DateFormat _dateFormat = intl.DateFormat('yyyy-MM-dd HH:mm');
  bool _lookupsLoaded = false;
  String? _lastError;
  String? _lastRouteSignature;

  @override
  void initState() {
    super.initState();
    _controller = ProductController(
      productRepository: GetIt.I<ProductRepository>(),
      vendorRepository: GetIt.I<VendorRepository>(),
      uomRepository: GetIt.I<UomRepository>(),
    )..addListener(_handleControllerUpdate);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _maybeApplyRoute();
  }

  @override
  void didUpdateWidget(covariant _ProductEnabledPage oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.routeUri != oldWidget.routeUri) {
      _maybeApplyRoute();
    }
  }

  void _handleControllerUpdate() {
    final error = _controller.errorMessage;
    if (error != null && error != _lastError && mounted) {
      _lastError = error;
      final messenger = ScaffoldMessenger.maybeOf(context);
      if (messenger != null) {
        messenger.showSnackBar(SnackBar(content: Text(error)));
      }
      _controller.clearError();
    }
  }

  @override
  void dispose() {
    _controller.removeListener(_handleControllerUpdate);
    _controller.dispose();
    _searchController.dispose();
    _searchFocus.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final theme = ShadTheme.of(context);

    return AnimatedBuilder(
      animation: _controller,
      builder: (context, _) {
        final result = _controller.result;
        final products = result?.items ?? const <Product>[];
        final totalCount = result?.total ?? 0;
        final currentPage = result?.page ?? 1;
        final totalPages = result == null || result.pageSize == 0
            ? 1
            : (result.total / result.pageSize).ceil().clamp(1, 9999);

        final showReset =
            _searchController.text.isNotEmpty ||
            _controller.vendorFilter != null ||
            _controller.uomFilter != null ||
            _controller.statusFilter != ProductStatusFilter.all;

        return AppLayout(
          title: '장비 모델(제품) 관리',
          subtitle: '제품코드, 제조사, 단위 정보를 관리합니다.',
          breadcrumbs: const [
            AppBreadcrumbItem(label: '대시보드', path: dashboardRoutePath),
            AppBreadcrumbItem(label: '마스터', path: '/masters/products'),
            AppBreadcrumbItem(label: '제품'),
          ],
          actions: [
            ShadButton(
              leading: const Icon(LucideIcons.plus, size: 16),
              onPressed: _controller.isSubmitting
                  ? null
                  : _openProductCreateDialog,
              child: const Text('신규 등록'),
            ),
          ],
          toolbar: FilterBar(
            actions: [
              ShadButton.outline(
                onPressed: _controller.isLoading ? null : _applyFilters,
                child: const Text('검색 적용'),
              ),
              if (showReset)
                ShadButton.ghost(
                  onPressed: _controller.isLoading
                      ? null
                      : () {
                          _searchController.clear();
                          _searchFocus.requestFocus();
                          _updateRoute(
                            page: 1,
                            queryOverride: '',
                            vendorOverride: null,
                            uomOverride: null,
                            statusOverride: ProductStatusFilter.all,
                          );
                        },
                  child: const Text('초기화'),
                ),
            ],
            children: [
              ConstrainedBox(
                constraints: const BoxConstraints(maxWidth: 260),
                child: ShadInput(
                  controller: _searchController,
                  focusNode: _searchFocus,
                  placeholder: const Text('제품코드, 제품명 검색'),
                  leading: const Icon(LucideIcons.search, size: 16),
                  onSubmitted: (_) => _applyFilters(),
                ),
              ),
              ConstrainedBox(
                constraints: const BoxConstraints(maxWidth: 220),
                child: ShadSelect<int?>(
                  key: ValueKey(_controller.vendorFilter),
                  initialValue: _controller.vendorFilter,
                  placeholder: const Text('제조사 전체'),
                  selectedOptionBuilder: (context, value) {
                    if (value == null) {
                      return const Text('제조사 전체');
                    }
                    final vendor = _controller.vendorOptions.firstWhere(
                      (v) => v.id == value,
                      orElse: () =>
                          Vendor(id: value, vendorCode: '', vendorName: ''),
                    );
                    return Text(vendor.vendorName);
                  },
                  onChanged: (value) =>
                      _updateRoute(page: 1, vendorOverride: value),
                  options: [
                    const ShadOption<int?>(value: null, child: Text('제조사 전체')),
                    ..._controller.vendorOptions.map(
                      (vendor) => ShadOption<int?>(
                        value: vendor.id,
                        child: Text(vendor.vendorName),
                      ),
                    ),
                  ],
                ),
              ),
              ConstrainedBox(
                constraints: const BoxConstraints(maxWidth: 220),
                child: ShadSelect<int?>(
                  key: ValueKey(_controller.uomFilter),
                  initialValue: _controller.uomFilter,
                  placeholder: const Text('단위 전체'),
                  selectedOptionBuilder: (context, value) {
                    if (value == null) {
                      return const Text('단위 전체');
                    }
                    final uom = _controller.uomOptions.firstWhere(
                      (u) => u.id == value,
                      orElse: () => Uom(id: value, uomName: ''),
                    );
                    return Text(uom.uomName);
                  },
                  onChanged: (value) =>
                      _updateRoute(page: 1, uomOverride: value),
                  options: [
                    const ShadOption<int?>(value: null, child: Text('단위 전체')),
                    ..._controller.uomOptions.map(
                      (uom) => ShadOption<int?>(
                        value: uom.id,
                        child: Text(uom.uomName),
                      ),
                    ),
                  ],
                ),
              ),
              ConstrainedBox(
                constraints: const BoxConstraints(maxWidth: 200),
                child: ShadSelect<ProductStatusFilter>(
                  key: ValueKey(_controller.statusFilter),
                  initialValue: _controller.statusFilter,
                  selectedOptionBuilder: (context, filter) =>
                      Text(_statusLabel(filter)),
                  onChanged: (value) {
                    if (value == null) return;
                    _updateRoute(page: 1, statusOverride: value);
                  },
                  options: ProductStatusFilter.values
                      .map(
                        (filter) => ShadOption(
                          value: filter,
                          child: Text(_statusLabel(filter)),
                        ),
                      )
                      .toList(),
                ),
              ),
            ],
          ),
          child: ShadCard(
            title: ResponsiveStackedRow(
              leading: Text('제품 목록', style: theme.textTheme.h3),
              trailing: Align(
                alignment: Alignment.centerRight,
                child: Text('$totalCount건', style: theme.textTheme.muted),
              ),
            ),
            footer: ResponsiveStackedRow(
              gap: 8,
              breakpoint: 420,
              leading: Text(
                '페이지 $currentPage / $totalPages',
                style: theme.textTheme.small,
              ),
              trailing: Align(
                alignment: Alignment.centerRight,
                child: Wrap(
                  spacing: 8,
                  runSpacing: 8,
                  alignment: WrapAlignment.end,
                  runAlignment: WrapAlignment.end,
                  children: [
                    SuperportPaginationControls(
                      currentPage: currentPage,
                      totalPages: totalPages,
                      isBusy: _controller.isLoading,
                      onPageSelected: _goToPage,
                    ),
                  ],
                ),
              ),
            ),
            child: _controller.isLoading
                ? const Padding(
                    padding: EdgeInsets.all(48),
                    child: Center(child: CircularProgressIndicator()),
                  )
                : products.isEmpty
                ? Padding(
                    padding: const EdgeInsets.all(32),
                    child: Text(
                      '조건에 맞는 제품이 없습니다.',
                      style: theme.textTheme.muted,
                    ),
                  )
                : _ProductTable(
                    products: products,
                    dateFormat: _dateFormat,
                    onProductTap: _controller.isSubmitting
                        ? null
                        : _openProductDetailDialog,
                  ),
          ),
        );
      },
    );
  }

  void _applyFilters() {
    final keyword = _searchController.text.trim();
    _controller.updateQuery(keyword);
    _updateRoute(page: 1, queryOverride: keyword);
  }

  String _statusLabel(ProductStatusFilter filter) {
    switch (filter) {
      case ProductStatusFilter.all:
        return '전체(사용/미사용)';
      case ProductStatusFilter.activeOnly:
        return '사용중';
      case ProductStatusFilter.inactiveOnly:
        return '미사용';
    }
  }

  void _maybeApplyRoute() {
    final signature = widget.routeUri.toString();
    if (_lastRouteSignature == signature) {
      return;
    }
    _lastRouteSignature = signature;
    _applyRouteParameters();
  }

  void _applyRouteParameters() {
    final params = widget.routeUri.queryParameters;
    final query = params['q'] ?? '';
    final vendorParam = int.tryParse(params['vendor'] ?? '');
    final uomParam = int.tryParse(params['uom'] ?? '');
    final status = _statusFromParam(params['status']);
    final pageSizeParam = int.tryParse(params['page_size'] ?? '');
    final pageParam = int.tryParse(params['page'] ?? '');

    _searchController.text = query;
    _controller.updateQuery(query);
    _controller.updateVendorFilter(vendorParam);
    _controller.updateUomFilter(uomParam);
    _controller.updateStatusFilter(status);
    if (pageSizeParam != null && pageSizeParam > 0) {
      _controller.updatePageSize(pageSizeParam);
    }

    final page = pageParam != null && pageParam > 0 ? pageParam : 1;
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      setState(() {
        _lookupsLoaded = false;
      });
      await Future.wait([
        _controller.loadLookups(),
        _controller.fetch(page: page),
      ]);
      if (mounted) {
        setState(() {
          _lookupsLoaded = true;
        });
      }
    });
  }

  void _goToPage(int page) {
    final result = _controller.result;
    final int totalPages;
    if (result == null || result.pageSize == 0) {
      totalPages = 1;
    } else {
      final calculated = (result.total / result.pageSize).ceil();
      totalPages = calculated < 1 ? 1 : calculated;
    }
    if (page < 1) {
      page = 1;
    } else if (page > totalPages) {
      page = totalPages;
    }
    _updateRoute(page: page);
  }

  void _updateRoute({
    required int page,
    String? queryOverride,
    int? vendorOverride,
    int? uomOverride,
    ProductStatusFilter? statusOverride,
    int? pageSizeOverride,
  }) {
    final query = queryOverride ?? _controller.query;
    final vendor = vendorOverride ?? _controller.vendorFilter;
    final uom = uomOverride ?? _controller.uomFilter;
    final status = statusOverride ?? _controller.statusFilter;
    final pageSize = pageSizeOverride ?? _controller.pageSize;

    final params = <String, String>{};
    if (query.isNotEmpty) {
      params['q'] = query;
    }
    if (vendor != null) {
      params['vendor'] = vendor.toString();
    }
    if (uom != null) {
      params['uom'] = uom.toString();
    }
    final statusParam = _encodeStatus(status);
    if (statusParam != null) {
      params['status'] = statusParam;
    }
    if (page > 1) {
      params['page'] = page.toString();
    }
    if (pageSize > 0 && pageSize != ProductController.defaultPageSize) {
      params['page_size'] = pageSize.toString();
    }

    final uri = Uri(
      path: widget.routeUri.path,
      queryParameters: params.isEmpty ? null : params,
    );
    final newLocation = uri.toString();
    if (widget.routeUri.toString() == newLocation) {
      _controller.fetch(page: page);
      return;
    }
    GoRouter.of(context).go(newLocation);
  }

  ProductStatusFilter _statusFromParam(String? value) {
    switch (value) {
      case 'active':
        return ProductStatusFilter.activeOnly;
      case 'inactive':
        return ProductStatusFilter.inactiveOnly;
      default:
        return ProductStatusFilter.all;
    }
  }

  String? _encodeStatus(ProductStatusFilter filter) {
    switch (filter) {
      case ProductStatusFilter.all:
        return null;
      case ProductStatusFilter.activeOnly:
        return 'active';
      case ProductStatusFilter.inactiveOnly:
        return 'inactive';
    }
  }

  Future<void> _openProductCreateDialog() async {
    if (!_lookupsLoaded) {
      _showSnack('선택 목록을 불러오는 중입니다. 잠시 후 다시 시도하세요.');
      return;
    }

    final result = await showProductDetailDialog(
      context: context,
      dateFormat: _dateFormat,
      vendorOptions: _controller.vendorOptions,
      uomOptions: _controller.uomOptions,
      onCreate: _controller.create,
      onUpdate: _controller.update,
      onDelete: _controller.delete,
      onRestore: _controller.restore,
    );

    if (result != null && mounted) {
      _showSnack(result.message);
      switch (result.action) {
        case ProductDetailDialogAction.created:
          unawaited(_controller.fetch(page: 1));
          break;
        case ProductDetailDialogAction.updated:
        case ProductDetailDialogAction.deleted:
        case ProductDetailDialogAction.restored:
          final currentPage = _controller.result?.page ?? 1;
          unawaited(_controller.fetch(page: currentPage));
          break;
      }
    }
  }

  Future<void> _openProductDetailDialog(Product product) async {
    final productId = product.id;
    if (productId == null) {
      _showSnack('ID 정보가 없어 상세를 열 수 없습니다.');
      return;
    }

    final result = await showProductDetailDialog(
      context: context,
      dateFormat: _dateFormat,
      product: product,
      vendorOptions: _controller.vendorOptions,
      uomOptions: _controller.uomOptions,
      onCreate: _controller.create,
      onUpdate: _controller.update,
      onDelete: _controller.delete,
      onRestore: _controller.restore,
    );

    if (result != null && mounted) {
      _showSnack(result.message);
      unawaited(_controller.fetch(page: _controller.result?.page ?? 1));
    }
  }

  void _showSnack(String message) {
    if (!mounted) {
      return;
    }
    final messenger = ScaffoldMessenger.maybeOf(context);
    if (messenger == null) {
      return;
    }
    messenger.showSnackBar(SnackBar(content: Text(message)));
  }
}

class _ProductTable extends StatelessWidget {
  const _ProductTable({
    required this.products,
    required this.dateFormat,
    required this.onProductTap,
  });

  final List<Product> products;
  final intl.DateFormat dateFormat;
  final void Function(Product product)? onProductTap;

  @override
  Widget build(BuildContext context) {
    final columns = const [
      Text('ID'),
      Text('제품코드'),
      Text('제품명'),
      Text('제조사'),
      Text('단위'),
      Text('사용'),
      Text('삭제'),
      Text('비고'),
      Text('변경일시'),
    ];

    return SuperportTable(
      columns: columns,
      rows: products
          .map(
            (product) => <Widget>[
              Text(product.id?.toString() ?? '-'),
              Text(product.productCode),
              Text(product.productName),
              Text(product.vendor?.vendorName ?? '-'),
              Text(product.uom?.uomName ?? '-'),
              Text(product.isActive ? 'Y' : 'N'),
              Text(product.isDeleted ? 'Y' : '-'),
              Text(product.note?.isEmpty ?? true ? '-' : product.note!),
              Text(
                product.updatedAt == null
                    ? '-'
                    : dateFormat.format(product.updatedAt!.toLocal()),
              ),
            ],
          )
          .toList(),
      rowHeight: 56,
      maxHeight: 520,
      onRowTap: onProductTap == null
          ? null
          : (index) => onProductTap!(products[index]),
      columnSpanExtent: (index) => switch (index) {
        2 => const FixedTableSpanExtent(200),
        3 => const FixedTableSpanExtent(180),
        7 => const FixedTableSpanExtent(220),
        8 => const FixedTableSpanExtent(160),
        _ => const FixedTableSpanExtent(120),
      },
    );
  }
}
