import 'dart:convert';
import 'dart:math';

import 'package:absen/config/config.dart';
import 'package:absen/models/attendance_area.dart';
import 'package:absen/widgets/google_map_web_view.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:http/http.dart' as http;

import 'checkout_photo_screen.dart';

class CheckoutScreen extends StatefulWidget {
  final String token;
  const CheckoutScreen({Key? key, required this.token}) : super(key: key);

  @override
  State<CheckoutScreen> createState() => _CheckoutScreenState();
}

class _CheckoutScreenState extends State<CheckoutScreen> {
  Position? _position;
  GoogleMapController? _mapController;
  bool _isLoading = false;
  bool _canCheckout = false;
  bool _checkedStatus = false;
  List<AttendanceArea> _areas = [];

  LatLng? get _latLng =>
      _position != null
          ? LatLng(_position!.latitude, _position!.longitude)
          : null;

  @override
  void initState() {
    super.initState();
    _checkTodayStatus();
    _fetchAttendanceAreas();
    _getLocation();
  }

  Future<void> _checkTodayStatus() async {
    setState(() => _checkedStatus = false);
    final url = Uri.parse(
      '${AppConfig.baseUrl}/api/employee/attendance/today-status',
    );
    try {
      final resp = await http.get(
        url,
        headers: {
          'Authorization': 'Bearer ${widget.token}',
          'Accept': 'application/json',
        },
      );
      if (resp.statusCode == 200) {
        final data = jsonDecode(resp.body)['data'];
        setState(() {
          _canCheckout = data['clock_in'] != null && data['clock_out'] == null;
        });
      } else {
        setState(() => _canCheckout = false);
      }
    } catch (_) {
      setState(() => _canCheckout = false);
    } finally {
      setState(() => _checkedStatus = true);
    }
  }

  Future<void> _fetchAttendanceAreas() async {
    final uri = Uri.parse('${AppConfig.baseUrl}/api/employee/attendance/areas');
    // Asumsikan endpoint mengembalikan JSON array: [ { center_lat, center_lng, radius }, ... ]
    try {
      final resp = await http.get(
        uri,
        headers: {'Authorization': 'Bearer ${widget.token}'},
      );
      if (resp.statusCode == 200) {
        final List<dynamic> data = jsonDecode(resp.body);
        final List<AttendanceArea> fetched =
            data.map((e) {
              return AttendanceArea(
                lat: (e['center_lat'] as num).toDouble(),
                lng: (e['center_lng'] as num).toDouble(),
                radius: (e['radius'] as num).toDouble(),
              );
            }).toList();
        setState(() {
          _areas = fetched;
        });
        if (_mapController != null && _position != null) {
          _moveCameraToBounds();
        }
      }
    } catch (_) {
      // Jika API lama hanya mengirim satu area, bisa fallback:
      // final single = jsonDecode(resp.body);
      // setState(() => _areas = [AttendanceArea(...)] );
    }
  }

  Future<void> _getLocation() async {
    try {
      bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
      if (!serviceEnabled) {
        await Geolocator.openLocationSettings();
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Aktifkan layanan lokasi!')),
        );
        return;
      }
      LocationPermission permission = await Geolocator.checkPermission();
      if (permission == LocationPermission.denied) {
        permission = await Geolocator.requestPermission();
        if (permission == LocationPermission.denied) {
          ScaffoldMessenger.of(
            context,
          ).showSnackBar(const SnackBar(content: Text('Izin lokasi ditolak!')));
          return;
        }
      }
      if (permission == LocationPermission.deniedForever) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Izin lokasi permanen ditolak!')),
        );
        return;
      }
      final pos = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high,
      );
      setState(() => _position = pos);
      if (_mapController != null && _areas.isNotEmpty) {
        _moveCameraToBounds();
      }
    } catch (e) {
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(SnackBar(content: Text('Gagal mengambil lokasi: $e')));
    }
  }

  void _moveCameraToBounds() {
    if (_mapController == null || _position == null) return;
    // kumpulkan semua LatLng: posisi user + semua pusat area
    final List<LatLng> points = [
      LatLng(_position!.latitude, _position!.longitude),
      ..._areas.map((a) => LatLng(a.lat, a.lng)),
    ];
    double south = points.first.latitude, north = points.first.latitude;
    double west = points.first.longitude, east = points.first.longitude;
    for (var p in points) {
      south = min(south, p.latitude);
      north = max(north, p.latitude);
      west = min(west, p.longitude);
      east = max(east, p.longitude);
    }
    final bounds = LatLngBounds(
      southwest: LatLng(south, west),
      northeast: LatLng(north, east),
    );
    Future.delayed(const Duration(milliseconds: 300), () {
      _mapController?.animateCamera(CameraUpdate.newLatLngBounds(bounds, 60));
    });
  }

  Future<void> _validateLocationAndNavigate() async {
    if (!_canCheckout) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Anda belum check-in hari ini!')),
      );
      return;
    }
    if (_position == null) {
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(const SnackBar(content: Text('Lokasi belum diambil!')));
      return;
    }
    // Opsional: cek client-side apakah posisi di dalam salah satu area
    bool insideAny = false;
    for (var area in _areas) {
      final dist = Geolocator.distanceBetween(
        _position!.latitude,
        _position!.longitude,
        area.lat,
        area.lng,
      ); // meter
      if (dist <= area.radius) {
        insideAny = true;
        break;
      }
    }
    if (!_areas.isEmpty && !insideAny) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Anda berada di luar semua area yang diizinkan.'),
        ),
      );
      return;
    }
    setState(() => _isLoading = true);
    final uri = Uri.parse(
      '${AppConfig.baseUrl}/api/employee/attendance/check-location',
    );
    try {
      final resp = await http.post(
        uri,
        headers: {
          'Authorization': 'Bearer ${widget.token}',
          'Content-Type': 'application/json',
        },
        body: jsonEncode({
          'latitude': _position!.latitude,
          'longitude': _position!.longitude,
          'type': 'out',
        }),
      );
      setState(() => _isLoading = false);
      final data = jsonDecode(resp.body);
      if (resp.statusCode == 200 && data['valid'] == true) {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder:
                (_) => CheckoutPhotoScreen(
                  token: widget.token,
                  position: _position!,
                ),
          ),
        );
      } else {
        final msg = data['message'] ?? 'Lokasi tidak valid';
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text(msg)));
      }
    } catch (e) {
      setState(() => _isLoading = false);
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(SnackBar(content: Text('Gagal validasi lokasi: $e')));
    }
  }

  @override
  Widget build(BuildContext context) {
    final buttonStyle = ElevatedButton.styleFrom(
      minimumSize: const Size.fromHeight(48),
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
    );
    if (!_checkedStatus) {
      return const Scaffold(body: Center(child: CircularProgressIndicator()));
    }
    return Scaffold(
      appBar: AppBar(title: const Text('Check-out'), centerTitle: true),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16.0),
          child: Column(
            children: [
              const SizedBox(height: 16),
              Text(
                _canCheckout
                    ? 'Tekan tombol di bawah untuk cek lokasi dan lanjut ambil foto.'
                    : 'Anda belum melakukan check-in hari ini atau sudah check-out.',
                textAlign: TextAlign.center,
                style: const TextStyle(fontSize: 16),
              ),
              const SizedBox(height: 16),
              Expanded(
                child: Card(
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(12),
                  ),
                  elevation: 4,
                  clipBehavior: Clip.hardEdge,
                  child: _buildMapArea(),
                ),
              ),
              const SizedBox(height: 16),
              SizedBox(
                width: double.infinity,
                child: ElevatedButton(
                  style: buttonStyle,
                  onPressed:
                      (_position != null && !_isLoading && _canCheckout)
                          ? _validateLocationAndNavigate
                          : null,
                  child:
                      _isLoading
                          ? const SizedBox(
                            width: 24,
                            height: 24,
                            child: CircularProgressIndicator(
                              color: Colors.white,
                              strokeWidth: 2,
                            ),
                          )
                          : const Text('Cek Lokasi & Lanjut'),
                ),
              ),
              const SizedBox(height: 16),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildMapArea() {
    if (kIsWeb) {
      if (_position == null) {
        return const Center(child: Text('Lokasi belum diambil'));
      }
      return GoogleMapWebView(
        latitude: _position!.latitude,
        longitude: _position!.longitude,
        areas: _areas,
      );
    }
    if (_latLng == null) {
      return const Center(child: Text('Lokasi belum diambil'));
    }
    // Tampilkan semua area sebagai circle & marker
    final markers = <Marker>{
      Marker(
        markerId: const MarkerId('me'),
        position: _latLng!,
        infoWindow: const InfoWindow(title: 'Lokasi Anda'),
      ),
    };
    for (int i = 0; i < _areas.length; i++) {
      final a = _areas[i];
      markers.add(
        Marker(
          markerId: MarkerId('area_$i'),
          position: LatLng(a.lat, a.lng),
          infoWindow: InfoWindow(title: 'Area Absen ${i + 1}'),
          icon: BitmapDescriptor.defaultMarkerWithHue(
            BitmapDescriptor.hueAzure,
          ),
        ),
      );
    }
    final circles = <Circle>{};
    for (int i = 0; i < _areas.length; i++) {
      final a = _areas[i];
      circles.add(
        Circle(
          circleId: CircleId('absen_area_$i'),
          center: LatLng(a.lat, a.lng),
          radius: a.radius,
          fillColor: Colors.blue.withOpacity(0.2),
          strokeColor: Colors.blue,
          strokeWidth: 2,
        ),
      );
    }
    return GoogleMap(
      initialCameraPosition: CameraPosition(
        target:
            _areas.isNotEmpty ? LatLng(_areas[0].lat, _areas[0].lng) : _latLng!,
        zoom: 16,
      ),
      markers: markers,
      circles: circles,
      onMapCreated: (ctrl) {
        _mapController = ctrl;
        if (_position != null && _areas.isNotEmpty) {
          _moveCameraToBounds();
        }
      },
      myLocationEnabled: true,
    );
  }
}
