import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:html/parser.dart';
import 'package:provider/provider.dart';
import 'package:relative_time/relative_time.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/sn_network.dart';
import 'package:surface/types/news.dart';
import 'package:surface/widgets/app_bar_leading.dart';
import 'package:surface/widgets/dialog.dart';
import 'package:surface/widgets/navigation/app_scaffold.dart';
import 'package:surface/widgets/universal_image.dart';
import 'package:very_good_infinite_list/very_good_infinite_list.dart';

class NewsScreen extends StatefulWidget {
  const NewsScreen({super.key});

  @override
  State<NewsScreen> createState() => _NewsScreenState();
}

class _NewsScreenState extends State<NewsScreen> {
  List<SnNewsSource>? _sources;

  @override
  initState() {
    super.initState();
    _fetchSources();
  }

  Future<void> _fetchSources() async {
    try {
      final sn = context.read<SnNetworkProvider>();
      final resp = await sn.client.get('/cgi/re/well-known/sources');
      _sources = List<SnNewsSource>.from(
        resp.data?.map((e) => SnNewsSource.fromJson(e)) ?? [],
      );
    } catch (err) {
      if (!mounted) return;
      context.showErrorDialog(err);
    } finally {
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    if (_sources == null) {
      return AppScaffold(
        appBar: AppBar(
          leading: AutoAppBarLeading(),
          title: Text('screenNews').tr(),
        ),
        body: Center(
          child: CircularProgressIndicator(),
        ),
      );
    }

    return DefaultTabController(
      length: _sources!.length + 1,
      child: AppScaffold(
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              SliverOverlapAbsorber(
                handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                sliver: SliverAppBar(
                  leading: AutoAppBarLeading(),
                  title: Text('screenNews').tr(),
                  bottom: TabBar(
                    isScrollable: true,
                    tabs: [
                      Tab(child: Text('newsAllSources'.tr())),
                      for (final source in _sources!) Tab(child: Text(source.label)),
                    ],
                  ),
                ),
              ),
            ];
          },
          body: TabBarView(
            children: [
              _NewsArticleListWidget(allSources: _sources!),
              for (final source in _sources!)
                _NewsArticleListWidget(
                  source: source.id,
                  allSources: _sources!,
                ),
            ],
          ),
        ),
      ),
    );
  }
}

class _NewsArticleListWidget extends StatefulWidget {
  final String? source;
  final List<SnNewsSource> allSources;

  const _NewsArticleListWidget({this.source, required this.allSources});

  @override
  State<_NewsArticleListWidget> createState() => _NewsArticleListWidgetState();
}

class _NewsArticleListWidgetState extends State<_NewsArticleListWidget> {
  bool _isBusy = false;

  int? _totalCount;
  final List<SnNewsArticle> _articles = List.empty(growable: true);

  Future<void> _fetchArticles() async {
    setState(() => _isBusy = true);

    try {
      final sn = context.read<SnNetworkProvider>();
      final resp = await sn.client.get('/cgi/re/news', queryParameters: {
        'take': 10,
        'offset': _articles.length,
        if (widget.source != null) 'source': widget.source,
      });
      _totalCount = resp.data['count'];
      _articles.addAll(List<SnNewsArticle>.from(
        resp.data['data']?.map((e) => SnNewsArticle.fromJson(e)) ?? [],
      ));
    } catch (err) {
      if (!mounted) return;
      context.showErrorDialog(err);
    } finally {
      setState(() => _isBusy = false);
    }
  }

  @override
  void initState() {
    super.initState();
    _fetchArticles();
  }

  @override
  Widget build(BuildContext context) {
    return MediaQuery.removePadding(
      context: context,
      removeTop: true,
      child: RefreshIndicator(
        onRefresh: _fetchArticles,
        child: InfiniteList(
          isLoading: _isBusy,
          itemCount: _articles.length,
          hasReachedMax: _totalCount != null && _articles.length >= _totalCount!,
          onFetchData: () {
            _fetchArticles();
          },
          itemBuilder: (context, index) {
            final article = _articles[index];

            final baseUri = Uri.parse(article.url);
            final baseUrl = '${baseUri.scheme}://${baseUri.host}';

            final htmlDescription = parse(article.description);
            final date = article.publishedAt ?? article.createdAt;

            return Card(
              child: InkWell(
                radius: 8,
                onTap: () {
                  GoRouter.of(context).pushNamed(
                    'newsDetail',
                    pathParameters: {'hash': article.hash},
                  );
                },
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    if (article.thumbnail.isNotEmpty && !article.thumbnail.endsWith('.svg'))
                      ClipRRect(
                        borderRadius: BorderRadius.all(Radius.circular(8)),
                        child: AspectRatio(
                          aspectRatio: 16 / 9,
                          child: AutoResizeUniversalImage(
                            article.thumbnail.startsWith('http') ? article.thumbnail : '$baseUrl/${article.thumbnail}',
                          ),
                        ),
                      ),
                    const Gap(16),
                    Text(article.title).textStyle(Theme.of(context).textTheme.titleLarge!).padding(horizontal: 16),
                    const Gap(8),
                    Text(htmlDescription.children.map((ele) => ele.text.trim()).join())
                        .textStyle(Theme.of(context).textTheme.bodyMedium!)
                        .padding(horizontal: 16),
                    const Gap(8),
                    Row(
                      spacing: 2,
                      children: [
                        Text(widget.allSources.where((x) => x.id == article.source).first.label)
                            .textStyle(Theme.of(context).textTheme.bodySmall!),
                      ],
                    ).opacity(0.75).padding(horizontal: 16),
                    Row(
                      spacing: 2,
                      children: [
                        Text(DateFormat().format(date)).textStyle(Theme.of(context).textTheme.bodySmall!),
                        Text(' ยท ').textStyle(Theme.of(context).textTheme.bodySmall!).bold(),
                        Text(RelativeTime(context).format(date)).textStyle(Theme.of(context).textTheme.bodySmall!),
                      ],
                    ).opacity(0.75).padding(horizontal: 16),
                    const Gap(16),
                  ],
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}