import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:html/parser.dart' as parser;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:url_launcher/url_launcher.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData.dark(useMaterial3: true).copyWith(
        colorScheme: ColorScheme.fromSeed(
            seedColor: Colors.blueAccent, brightness: Brightness.dark),
        scaffoldBackgroundColor: const Color(0xFF121212),
        cardColor: const Color(0xFF1E1E1E),
      ),
      home: const AnimeListScreen(),
    );
  }
}

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

  @override
  AnimeListScreenState createState() => AnimeListScreenState();
}

class AnimeListScreenState extends State<AnimeListScreen> {
  final List<Map<String, String>> _animeList = [];
  bool _isLoading = true;
  bool _hasMore = true;
  int _currentPage = 1;
  final ScrollController _scrollController = ScrollController();
  static const userAgent =
      'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36';

  @override
  void initState() {
    super.initState();
    _fetchAnimeList();
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        _loadMore();
      }
    });
  }

  Future<void> _fetchAnimeList([int page = 1]) async {
    const baseUrl = 'https://www.okanime.xyz/espisode-list';
    final url = '$baseUrl?page=$page';
    try {
      final response = await http.get(Uri.parse(url), headers: {
        'User-Agent': userAgent,
      });
      if (response.statusCode == 200) {
        final document = parser.parse(response.body);
        final animeElements =
            document.querySelectorAll('div.section-content.mt-3 > div > div');
        if (animeElements.isEmpty) {
          _hasMore = false;
        } else {
          final newAnimeList = animeElements.map((element) {
            final titleElement = element.querySelector('div.anime-title > h4');
            final episodeElement =
                element.querySelector('div.anime-title > h5');
            final imgElement = element.querySelector('div.episode-image > img');
            final urlElement = element.querySelector('div.episode-image > a');
            return {
              'title': titleElement?.text.trim() ?? 'No title found',
              'episode': episodeElement?.text.trim() ?? 'No episode number found',
              'imgUrl': imgElement?.attributes['src'] ?? '',
              'pageUrl': urlElement?.attributes['href'] ?? '',
            };
          }).toList();
          setState(() {
            _animeList.addAll(newAnimeList);
            _isLoading = false;
          });
        }
      } else {
        _handleError('Failed to load page $page');
      }
    } catch (e) {
      _handleError('Error fetching anime list: $e');
    }
  }

  void _handleError(String message) {
    if (kDebugMode) {
      print(message);
    }
    setState(() {
      _isLoading = false;
    });
    ScaffoldMessenger.of(context)
        .showSnackBar(SnackBar(content: Text(message)));
  }

  void _loadMore() {
    if (!_isLoading && _hasMore) {
      setState(() {
        _isLoading = true;
        _currentPage++;
      });
      _fetchAnimeList(_currentPage);
    }
  }

  Future<String> _fetchStreamUrl(String pageUrl) async {
    try {
      final response = await http.get(Uri.parse(pageUrl), headers: {
        'User-Agent': userAgent,
      });
      if (response.statusCode == 200) {
        var document = parser.parse(response.body);
        var streamLinks =
            document.querySelectorAll('#streamlinks > a');
        for (var link in streamLinks) {
          if (link.text.contains('sendvid')) {
            var embedUrl = link.attributes['data-src'] ?? 'No stream URL found';
            if (embedUrl != 'No stream URL found') {
              final embedResponse = await http.get(Uri.parse(embedUrl), headers: {
                'User-Agent': userAgent,
              });
              if (embedResponse.statusCode == 200) {
                var embedDocument = parser.parse(embedResponse.body);
                var videoElement = embedDocument.querySelector('video source');
                return videoElement?.attributes['src'] ?? 'No .mp4 URL found';
              }
            }
          }
        }
      }
      return 'No .mp4 URL found';
    } catch (e) {
      if (kDebugMode) {
        print('Error fetching stream URL: $e');
      }
      return 'No .mp4 URL found';
    }
  }

  void _launchVideoUrl(String mp4Url) async {
    if (mp4Url != 'No .mp4 URL found') {
      if (await canLaunchUrl(Uri.parse(mp4Url))) {
        await launchUrl(
          Uri.parse(mp4Url),
          mode: LaunchMode.externalApplication,
        );
      } else {
        _handleError('Could not launch video URL');
      }
    } else {
      _handleError('Could not fetch video URL');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Anime List'),
      ),
      body: _isLoading && _animeList.isEmpty
          ? const Center(child: CircularProgressIndicator())
          : ListView.builder(
              controller: _scrollController,
              itemCount: _hasMore ? _animeList.length + 1 : _animeList.length,
              itemBuilder: (context, index) {
                if (index < _animeList.length) {
                  final anime = _animeList[index];
                  return Container(
                    margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(16),
                      gradient: const LinearGradient(
                        colors: [Color(0xFF2E7D32), Color(0xFF1B5E20)],
                        begin: Alignment.topLeft,
                        end: Alignment.bottomRight,
                      ),
                    ),
                    child: Card(
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(16),
                      ),
                      clipBehavior: Clip.antiAlias,
                      elevation: 2,
                      margin: EdgeInsets.zero,
                      child: Stack(
                        children: [
                          Padding(
                            padding: const EdgeInsets.all(8.0),
                            child: Row(
                              children: [
                                ClipRRect(
                                  borderRadius: BorderRadius.circular(8.0),
                                  child: CachedNetworkImage(
                                    imageUrl: anime['imgUrl']!,
                                    width: 120,
                                    height: 160,
                                    fit: BoxFit.cover,
                                    placeholder: (context, url) => const SizedBox(
                                      width: 120,
                                      height: 160,
                                      child: Center(
                                          child: CircularProgressIndicator()),
                                    ),
                                    errorWidget: (context, url, error) =>
                                        const Icon(Icons.error),
                                  ),
                                ),
                                const SizedBox(width: 16),
                                Expanded(
                                  child: Column(
                                    crossAxisAlignment: CrossAxisAlignment.start,
                                    children: [
                                      Text(
                                        anime['title']!,
                                        maxLines: 2,
                                        overflow: TextOverflow.ellipsis,
                                        style: const TextStyle(
                                          fontSize: 18,
                                          fontWeight: FontWeight.bold,
                                          color: Colors.white,
                                        ),
                                      ),
                                      const SizedBox(height: 8),
                                      Text(
                                        '${anime['episode']}',
                                        style: const TextStyle(
                                          fontSize: 14,
                                          color: Colors.white70,
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ),
                          Positioned(
                            bottom: 8,
                            right: 8,
                            child: ElevatedButton(
                              style: ElevatedButton.styleFrom(
                                shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(18.0),
                                ),
                              ),
                              onPressed: () async {
                                final mp4Url =
                                    await _fetchStreamUrl(anime['pageUrl']!);
                                _launchVideoUrl(mp4Url);
                              },
                              child: const Text('Watch Now'),
                            ),
                          ),
                        ],
                      ),
                    ),
                  );
                } else {
                  return Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Center(
                      child: _isLoading
                          ? const CircularProgressIndicator()
                          : const SizedBox(),
                    ),
                  );
                }
              },
            ),
    );
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }
} iwant build this app