import 'dart:ui';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';

import '../constants/breakpoints.dart';
import '../theme/app_theme.dart';
import 'banner_carousel_mixin.dart';
import 'circle_nav_icon_button.dart';
import 'frosted_panel.dart';
import 'smart_image.dart';


class BannerSlideData {
  final String? imageUrl;
  final String? fallbackImageUrl;
  final Map<String, String>? imageHeaders;


  final String? logoUrl;
  final String title;
  final String? overview;


  final String? rating;


  final List<String> primaryMetaLabels;


  final List<String> secondaryMetaLabels;

  const BannerSlideData({
    required this.imageUrl,
    required this.title,
    this.fallbackImageUrl,
    this.imageHeaders,
    this.logoUrl,
    this.overview,
    this.rating,
    this.primaryMetaLabels = const [],
    this.secondaryMetaLabels = const [],
  });
}


class BannerCarouselScaffold extends StatelessWidget {
  final BannerCarouselMixin controller;
  final List<BannerSlideData> slides;
  final ValueChanged<int> onSlideTap;


  final bool reserveLogoArea;

  const BannerCarouselScaffold({
    super.key,
    required this.controller,
    required this.slides,
    required this.onSlideTap,
    this.reserveLogoArea = false,
  });

  @override
  Widget build(BuildContext context) {
    if (slides.isEmpty) return const SizedBox.shrink();

    final compact = Breakpoints.isCompact(MediaQuery.sizeOf(context).width);
    if (compact) return _buildCompact(context);
    return _buildDesktop(context);
  }


  Widget _contentSwitcher({required bool compact}) {
    return IgnorePointer(
      child: AnimatedSwitcher(
        duration: const Duration(milliseconds: 300),
        switchInCurve: Curves.easeOut,
        switchOutCurve: Curves.easeOut,
        layoutBuilder: (currentChild, previousChildren) => Stack(
          fit: StackFit.expand,
          children: [
            ...previousChildren,
            if (currentChild != null) currentChild,
          ],
        ),
        child: _BannerSlideContent(
          key: ValueKey(controller.currentIndex),
          data: slides[controller.currentIndex],
          compact: compact,
          reserveLogoArea: reserveLogoArea,
        ),
      ),
    );
  }

  Widget _pageIndicator() {
    return FrostedPanel(
      radius: 999,
      enableBlur: false,
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
      color: Colors.black.withValues(alpha: 0.24),
      border: Border.all(color: Colors.white.withValues(alpha: 0.12)),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          for (var index = 0; index < slides.length; index++)
            GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () => controller.goToPage(index),
              child: AnimatedContainer(
                duration: const Duration(milliseconds: 240),
                curve: Curves.easeOut,
                width: controller.currentIndex == index ? 22 : 7,
                height: 7,
                margin: EdgeInsets.only(
                  right: index == slides.length - 1 ? 0 : 6,
                ),
                decoration: BoxDecoration(
                  color: controller.currentIndex == index
                      ? Colors.white
                      : const Color(0x66FFFFFF),
                  borderRadius: BorderRadius.circular(999),
                ),
              ),
            ),
        ],
      ),
    );
  }

  Widget _pageView({required bool compact}) {
    return PageView.builder(
      controller: controller.pageController,
      physics: compact ? null : const NeverScrollableScrollPhysics(),
      itemCount: slides.length,
      onPageChanged: controller.onPageChanged,
      itemBuilder: (context, index) {
        return _BannerSlide(data: slides[index], compact: compact);
      },
    );
  }

  Widget _buildCompact(BuildContext context) {
    final screenHeight = MediaQuery.sizeOf(context).height;
    final height = screenHeight * 0.55;
    final screenWidth = MediaQuery.sizeOf(context).width;
    controller.lastBannerWidth = screenWidth.isFinite && screenWidth > 0
        ? screenWidth
        : null;

    return SizedBox(
      height: height,
      child: GestureDetector(
        behavior: HitTestBehavior.opaque,
        onTap: () => onSlideTap(controller.currentIndex),
        child: Stack(
          fit: StackFit.expand,
          children: [
            _pageView(compact: true),
            _contentSwitcher(compact: true),
            Positioned(
              left: 0,
              right: 0,
              bottom: 20,
              child: Center(child: _pageIndicator()),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildDesktop(BuildContext context) {
    final tokens = context.appTokens;

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 24),
      child: LayoutBuilder(
        builder: (context, constraints) {
          final width = constraints.maxWidth;
          controller.lastBannerWidth = width.isFinite && width > 0
              ? width
              : null;
          final height = (width * 7 / 16).clamp(260.0, 500.0);
          return SizedBox(
            height: height,
            child: ClipRRect(
              borderRadius: BorderRadius.circular(tokens.panelRadius + 6),
              child: MouseRegion(
                cursor: SystemMouseCursors.click,
                onEnter: (_) => controller.setHovering(true),
                onExit: (_) => controller.setHovering(false),
                child: Stack(
                  fit: StackFit.expand,
                  children: [
                    _BlurredBackdropLayer(
                      data: slides[controller.currentIndex],
                      animateSwitch: slides.length > 1,
                    ),
                    GestureDetector(
                      behavior: HitTestBehavior.opaque,
                      onTap: () => onSlideTap(controller.currentIndex),
                      child: _pageView(compact: false),
                    ),
                    _contentSwitcher(compact: false),
                    Positioned(right: 22, bottom: 20, child: _pageIndicator()),
                    if (controller.hovering && slides.length > 1) ...[
                      Positioned(
                        left: 14,
                        top: 0,
                        bottom: 0,
                        child: Center(
                          child: CircleNavIconButton(
                            icon: Icons.chevron_left_rounded,
                            onPressed: controller.prevPage,
                            iconSize: 28,
                          ),
                        ),
                      ),
                      Positioned(
                        right: 14,
                        top: 0,
                        bottom: 0,
                        child: Center(
                          child: CircleNavIconButton(
                            icon: Icons.chevron_right_rounded,
                            onPressed: controller.nextPage,
                            iconSize: 28,
                          ),
                        ),
                      ),
                    ],
                  ],
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}


class _BlurredBackdropLayer extends StatelessWidget {
  final BannerSlideData data;
  final bool animateSwitch;

  const _BlurredBackdropLayer({
    required this.data,
    required this.animateSwitch,
  });

  @override
  Widget build(BuildContext context) {
    final image = _BlurredBackdropImage(
      key: ValueKey<String>(data.imageUrl ?? '__none__'),
      data: data,
    );

    if (!animateSwitch) return image;

    return AnimatedSwitcher(
      duration: const Duration(milliseconds: 200),
      switchInCurve: Curves.easeOut,
      switchOutCurve: Curves.easeOut,
      layoutBuilder: (currentChild, previousChildren) {
        return Stack(
          fit: StackFit.expand,
          children: [
            ...previousChildren,
            if (currentChild != null) currentChild,
          ],
        );
      },
      child: image,
    );
  }
}

class _BlurredBackdropImage extends StatelessWidget {
  final BannerSlideData data;

  const _BlurredBackdropImage({super.key, required this.data});

  @override
  Widget build(BuildContext context) {
    return ClipRect(
      child: Stack(
        fit: StackFit.expand,
        children: [
          ImageFiltered(
            imageFilter: ImageFilter.blur(
              sigmaX: 36,
              sigmaY: 36,
              tileMode: TileMode.clamp,
            ),
            child: SmartImage(
              url: data.imageUrl,
              fallbackUrls: [
                if (data.fallbackImageUrl != null) data.fallbackImageUrl!,
              ],
              httpHeaders: data.imageHeaders,
              borderRadius: 0,
              fit: BoxFit.cover,
              memCacheWidth: 800,
              fallbackIcon: null,
              placeholder: const ColoredBox(color: Colors.black),
            ),
          ),
          IgnorePointer(
            child: ColoredBox(color: Colors.black.withValues(alpha: 0.30)),
          ),
        ],
      ),
    );
  }
}


class _BannerSlide extends StatelessWidget {
  final BannerSlideData data;
  final bool compact;

  const _BannerSlide({required this.data, this.compact = false});

  @override
  Widget build(BuildContext context) {
    if (compact) {
      return Stack(
        fit: StackFit.expand,
        children: [
          SmartImage(
            url: data.imageUrl,
            fallbackUrls: [
              if (data.fallbackImageUrl != null) data.fallbackImageUrl!,
            ],
            borderRadius: 0,
            fit: BoxFit.cover,
            httpHeaders: data.imageHeaders,
            fallbackIcon: Icons.movie_outlined,
            placeholder: const SizedBox.expand(),
          ),
          DecoratedBox(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
                stops: const [0.0, 0.12, 0.4, 0.75, 1.0],
                colors: [
                  Colors.black.withValues(alpha: 0.35),
                  Colors.black.withValues(alpha: 0.12),
                  Colors.black.withValues(alpha: 0.0),
                  Colors.black.withValues(alpha: 0.35),
                  Colors.black.withValues(alpha: 0.70),
                ],
              ),
            ),
          ),
        ],
      );
    }

    return Stack(
      fit: StackFit.expand,
      children: [
        ImageFiltered(
          imageFilter: ImageFilter.blur(
            sigmaX: 36,
            sigmaY: 36,
            tileMode: TileMode.mirror,
          ),
          child: SmartImage(
            url: data.imageUrl,
            fallbackUrls: [
              if (data.fallbackImageUrl != null) data.fallbackImageUrl!,
            ],
            borderRadius: 0,
            fit: BoxFit.cover,
            httpHeaders: data.imageHeaders,
            fallbackIcon: null,
            placeholder: const SizedBox.expand(),
          ),
        ),
        DecoratedBox(
          decoration: BoxDecoration(
            color: Colors.black.withValues(alpha: 0.32),
          ),
        ),
        SmartImage(
          url: data.imageUrl,
          fallbackUrls: [
            if (data.fallbackImageUrl != null) data.fallbackImageUrl!,
          ],
          borderRadius: 0,
          fit: BoxFit.contain,
          httpHeaders: data.imageHeaders,
          fallbackIcon: Icons.movie_outlined,
          placeholder: const SizedBox.expand(),
        ),
        DecoratedBox(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              stops: const [0.0, 0.35, 0.6, 1.0],
              colors: [
                Colors.black.withValues(alpha: 0.0),
                Colors.black.withValues(alpha: 0.03),
                Colors.black.withValues(alpha: 0.25),
                Colors.black.withValues(alpha: 0.55),
              ],
            ),
          ),
        ),
      ],
    );
  }
}


class _BannerSlideContent extends StatelessWidget {
  final BannerSlideData data;
  final bool compact;
  final bool reserveLogoArea;

  const _BannerSlideContent({
    super.key,
    required this.data,
    required this.compact,
    required this.reserveLogoArea,
  });

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final tokens = context.appTokens;
    final ratingColor = tokens.ratingColor;

    final hasMetaInfo =
        data.rating != null ||
        data.primaryMetaLabels.isNotEmpty ||
        data.secondaryMetaLabels.isNotEmpty;

    final titleFontSize = compact ? 24.0 : 32.0;
    final titleText = Text(
      data.title,
      maxLines: 2,
      overflow: TextOverflow.ellipsis,
      style: theme.textTheme.titleLarge?.copyWith(
        color: Colors.white,
        fontSize: titleFontSize,
        height: 1.0,
      ),
    );

    final padding = compact
        ? const EdgeInsets.only(left: 24, bottom: 64, right: 24)
        : const EdgeInsets.only(left: 32, bottom: 32);

    return Align(
      alignment: Alignment.bottomLeft,
      child: Padding(
        padding: padding,
        child: ConstrainedBox(
          constraints: const BoxConstraints(maxWidth: 480),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              if (reserveLogoArea) _buildLogoArea(titleText) else titleText,
              if (hasMetaInfo) ...[
                const SizedBox(height: 10),
                _MetaRow(
                  rating: data.rating,
                  ratingColor: ratingColor,
                  primaryLabels: data.primaryMetaLabels,
                  secondaryLabels: data.secondaryMetaLabels,
                ),
              ],
              if ((data.overview ?? '').trim().isNotEmpty) ...[
                const SizedBox(height: 12),
                Text(
                  data.overview!,
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                  style: theme.textTheme.bodyMedium?.copyWith(
                    color: Colors.white.withValues(alpha: 0.78),
                    height: 1.5,
                  ),
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }


  Widget _buildLogoArea(Widget titleText) {
    final logoHeight = compact ? 56.0 : 72.0;
    final logoMaxWidth = compact ? 240.0 : 320.0;

    return ConstrainedBox(
      constraints: BoxConstraints(maxWidth: logoMaxWidth),
      child: SizedBox(
        width: double.infinity,
        height: logoHeight,
        child: data.logoUrl != null
            ? CachedNetworkImage(
                imageUrl: data.logoUrl!,
                httpHeaders: data.imageHeaders,
                fit: BoxFit.contain,
                alignment: Alignment.bottomLeft,
                memCacheWidth: 960,
                fadeInDuration: const Duration(milliseconds: 300),
                placeholderFadeInDuration: Duration.zero,
                fadeOutDuration: const Duration(milliseconds: 300),
                placeholder: (_, _) => const SizedBox.shrink(),
                errorWidget: (_, _, _) =>
                    Align(alignment: Alignment.bottomLeft, child: titleText),
              )
            : Align(alignment: Alignment.bottomLeft, child: titleText),
      ),
    );
  }
}

class _MetaRow extends StatelessWidget {
  final String? rating;
  final Color ratingColor;
  final List<String> primaryLabels;
  final List<String> secondaryLabels;

  const _MetaRow({
    required this.rating,
    required this.ratingColor,
    required this.primaryLabels,
    required this.secondaryLabels,
  });

  @override
  Widget build(BuildContext context) {
    final style = Theme.of(context).textTheme.bodySmall;
    final children = <Widget>[];

    void addSep() {
      children.add(
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 6),
          child: Text(
            '·',
            style: style?.copyWith(color: Colors.white.withValues(alpha: 0.38)),
          ),
        ),
      );
    }

    if (rating != null) {
      children.add(
        Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(Icons.star_rounded, size: 13, color: ratingColor),
            const SizedBox(width: 3),
            Text(
              rating!,
              style: style?.copyWith(
                color: Colors.white,
                fontWeight: FontWeight.w700,
              ),
            ),
          ],
        ),
      );
    }

    for (final label in primaryLabels) {
      if (children.isNotEmpty) addSep();
      children.add(
        Text(
          label,
          style: style?.copyWith(color: Colors.white.withValues(alpha: 0.80)),
        ),
      );
    }

    for (final label in secondaryLabels) {
      if (children.isNotEmpty) addSep();
      children.add(
        Text(
          label,
          style: style?.copyWith(color: Colors.white.withValues(alpha: 0.62)),
        ),
      );
    }

    return Row(mainAxisSize: MainAxisSize.min, children: children);
  }
}
