import flet as ft
from flet import canvas
import requests
from pages.clients_page import ClientsPage
from pages.transporters_page import TransportersPage
from pages.destinations_page import DestinationsPage
from pages.orders_page import OrdersPage
from pages.reports_page import ReportsPage
from pages.profile_page import ProfilePage
from pages.subscription_page import Subscription
from datetime import datetime
from pages.admin_page import Admin
from config import API_BASE_URL
from email.utils import parsedate_to_datetime

class DashboardPage:
    def __init__(self, page: ft.Page):
        self.page = page
        self.placeholder = ft.Container(
            expand=True, 
            padding=ft.padding.only(
                top=30,     
                left=20,   
                right=20,   
                bottom=20   
            ),
        )
        self.all_clients = self.get_all_clients() 
        self.all_orders = self.get_all_orders()
        self.all_transporters = self.get_all_transporters()
        self.orders = []
        self.profit = self.get_profit()
        self.logo = ft.Image(
            src=f"images/{self.page.client_storage.get('logo_filename') or 'truck_logo_black.png'}",
            width=60,
            height=60,
            fit=ft.ImageFit.CONTAIN
        )
        self.logo_container = ft.Container(
            content=ft.Column(
                controls=[self.logo],
                alignment=ft.MainAxisAlignment.CENTER,
                horizontal_alignment=ft.CrossAxisAlignment.CENTER,
                spacing=5,
            ),
            padding=10,
        )
        self.user = self.get_user()

    def _on_resize(self, e):
        # Hide logo in the navigation rail if window height is too small
        try:
            height = e.height or 0
        except Exception:
            height = 0
        if hasattr(self, "logo_container"):
            self.logo_container.visible = height > 600  # threshold in pixels; adjust if needed
            self.logo_container.update()
        self.subscription_status = ft.Text(
            "", 
            color=ft.Colors.RED
        )
        

    # --- helper to parse created_at values coming from API in multiple formats ---
    def _parse_dt(self, s):
        if not s:
            return None
        if isinstance(s, datetime):
            return s
        try:
            # First try ISO 8601 (with or without microseconds)
            return datetime.fromisoformat(s.replace("Z", "+00:00"))
        except Exception:
            pass
        try:
            # Then try RFC 2822 / RFC 1123 (e.g., 'Mon, 18 Aug 2025 19:22:19 GMT')
            return parsedate_to_datetime(s)
        except Exception:
            pass
        try:
            # Fallback: common ISO without microseconds
            return datetime.strptime(s, "%Y-%m-%dT%H:%M:%S")
        except Exception:
            return None

    def get_user(self):
        token = self.page.client_storage.get("token")
        if not token:
            self.message.value = "Unauthorized: No token"
            return
        response = requests.get(f"{API_BASE_URL}/profile/", headers={"Authorization": f"Bearer {token}"})
        #print(response.text)
        return response.json() if response.status_code == 200 else None

    def on_admin_btn_click(self, e):
        admin = Admin(self.page, self)
        self.placeholder.content = admin.build()
        self.placeholder.update() 

    def get_all_transporters(self):
        try:
            token = self.page.client_storage.get("token")
            headers = {"Authorization": f"Bearer {token}"}
            response = requests.get(f"{API_BASE_URL}/transporters/", headers=headers)
            return response.json() if response.status_code == 200 else []
        except Exception as e:
            print("Error loading transporters:", e)


    def get_all_orders(self):
        try:
            token = self.page.client_storage.get("token")
            headers = {"Authorization": f"Bearer {token}"}
            response = requests.get(f"{API_BASE_URL}/orders/list", headers=headers)
            return response.json() if response.status_code == 200 else []
        except Exception as e:
            print("Error loading orders:", e)

    def get_all_clients(self):
        try:
            token = self.page.client_storage.get("token")
            headers = {"Authorization": f"Bearer {token}"}
            response = requests.get(f"{API_BASE_URL}/clients/", headers=headers)
            return response.json() if response.status_code == 200 else []
        except Exception as e:
            print("Error loading clients:", e)

    def get_profit(self):
        date_today = datetime.now()
        month_first_day = date_today.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        #print(month_first_day)
        if len(self.all_orders)>0:
            for order in self.all_orders:
                if order.get('status') != 'active':
                    continue
                dt = self._parse_dt(order.get('created_at'))
                if dt and dt.date() >= month_first_day.date():
                    self.orders.append(order)
            all_profit = 0
            for order in self.orders:
                profit = round(order['received_price'] - order['paid_price'], 2)
                all_profit += profit
            return all_profit
        else:
            return 0


    def _build_dashboard_content(self):
        self.all_clients = self.get_all_clients() 
        self.all_orders = self.get_all_orders()
        self.all_transporters = self.get_all_transporters()
        self.orders = []
        self.profit = self.get_profit()
        
        summary_cards = ft.Row(
            controls=[     
                #self._summary_card("Clients", len(self.all_clients), ft.Icons.PEOPLE),
                #self._summary_card("Transporters", len(self.all_transporters), ft.Icons.LOCAL_SHIPPING),
                self._summary_card("Monthly Orders", len(self.orders), ft.Icons.RECEIPT_LONG),
                self._summary_card("Monthly Profit", self.profit, ft.Icons.SHOW_CHART),            
            ],
            spacing=20,
            wrap=True
        )

        # Prepare data for BarChart using flet_charts
        from collections import defaultdict
        daily_orders = defaultdict(int)
        for order in self.orders:
            try:
                dt = self._parse_dt(order.get('created_at'))
                if dt:
                    daily_orders[dt.day] += 1
            except Exception as e:
                print("Invalid date:", order['created_at'])

        max_value = max(daily_orders.values(), default=1)

        bar_groups = []
        for day in sorted(daily_orders.keys()):
            value = daily_orders[day]
            bar_groups.append(
                ft.BarChartGroup(
                    x=day,
                    bar_rods=[
                        ft.BarChartRod(
                            from_y=0,
                            to_y=value,
                            width=20,
                            color=ft.Colors.BLUE
                        )
                    ]
                )
            )

        chart_1 = ft.Container(
            expand=True,
            bgcolor=ft.Colors.BLUE_50,
            padding=10,
            border_radius=20,
            content=ft.Column([
                ft.Text("Monthly Orders", size=16, weight=ft.FontWeight.BOLD),
                ft.BarChart(
                    bar_groups=bar_groups,
                    border=ft.border.all(1, ft.Colors.GREY_300),
                    left_axis=ft.ChartAxis(
                        labels_size=40,
                        labels=[
                            ft.ChartAxisLabel(
                                value=i,
                                label=ft.Text(str(i), size=10)
                            ) for i in range(0, max_value + 1, max(1, max_value // 5))
                        ],
                    ),
                    bottom_axis=ft.ChartAxis(
                        labels=[
                            ft.ChartAxisLabel(
                                value=day,
                                label=ft.Text(str(day), size=10)
                            ) for day in sorted(daily_orders.keys())
                        ],
                    ),
                    tooltip_bgcolor=ft.Colors.with_opacity(0.8, ft.Colors.BLUE),
                    expand=True,
                    animate=True
                )
            ])
        )

        # Calculate daily profit
        from collections import defaultdict
        daily_profit = defaultdict(float)
        for order in self.orders:
            try:
                dt = self._parse_dt(order.get('created_at'))
                if dt:
                    profit = order["received_price"] - order["paid_price"]
                    daily_profit[dt.day] += profit
            except Exception as e:
                print("Invalid date in profit chart:", order['created_at'])

        max_profit = max(daily_profit.values(), default=1)

        profit_bar_groups = []
        for day in sorted(daily_profit.keys()):
            value = daily_profit[day]
            profit_bar_groups.append(
                ft.BarChartGroup(
                    x=day,
                    bar_rods=[
                        ft.BarChartRod(
                            from_y=0,
                            to_y=value,
                            width=20,
                            color=ft.Colors.GREEN
                        )
                    ]
                )
            )

        chart_2 = ft.Container(
            expand=True,
            bgcolor=ft.Colors.BLUE_50,
            padding=10,
            border_radius=20,
            content=ft.Column([
                ft.Text("Daily Profit", size=16, weight=ft.FontWeight.BOLD),
                ft.BarChart(
                    bar_groups=profit_bar_groups,
                    border=ft.border.all(1, ft.Colors.GREY_300),
                    left_axis=ft.ChartAxis(
                        labels_size=40,
                        labels=[
                            ft.ChartAxisLabel(
                                value=i,
                                label=ft.Text(str(i), size=10)
                            ) for i in range(0, int(max_profit)+1, max(1, int(max_profit)//5))
                        ],
                    ),
                    bottom_axis=ft.ChartAxis(
                        labels=[
                            ft.ChartAxisLabel(
                                value=day,
                                label=ft.Text(str(day), size=10)
                            ) for day in sorted(daily_profit.keys())
                        ],
                    ),
                    tooltip_bgcolor=ft.Colors.with_opacity(0.8, ft.Colors.GREEN),
                    expand=True,
                    animate=True
                )
            ])
        )

        charts = ft.Row(
            controls=[chart_1, chart_2],
            expand=True,
            spacing=20
        )

        if self.user:
            if self.get_subscription():
                if self.get_subscription()['end_date'] < datetime.today()-3:
                    self.subscription_status.value = "Your subscription will expire soon. Please Renew!"
                    self.subscription_status.update()
                elif self.get_subscription()['end_date'] > datetime.today():
                    self.subscription_status.value = "Your subscription has expired!"
                    self.subscription_status.update()
                return ft.Column(
                    [
                        ft.Row(
                            [
                                summary_cards,
                                self.subscription_status
                            ],
                            alignment=ft.MainAxisAlignment.SPACE_BETWEEN
                        ),
                        charts
                    ],
                    spacing=20,
                    expand=True
                )
            else:
                return ft.Column(
                    controls=[
                        summary_cards,
                        charts
                    ],
                    spacing=20,
                    expand=True
                )
        else:
            return ft.Column(
            controls=[
                summary_cards,
                charts
            ],
            spacing=20,
            expand=True
        )

    def _summary_card(self, title, value, icon):
        return ft.Container(
            content=ft.Column(
                controls=[
                    ft.Icon(name=icon, size=30),
                    ft.Text(value, weight=ft.FontWeight.BOLD, size=18),
                    ft.Text(title, size=14)
                ],
                spacing=5,
                alignment=ft.MainAxisAlignment.CENTER
            ),
            width=150,
            height=100,
            padding=10,
            alignment=ft.alignment.center,
            border_radius=10,
            bgcolor=ft.Colors.BLUE_100
        )

    def _navigate(self, index):
        self.placeholder.content.clean()
        if index == 0:
            self.placeholder.content = self._build_dashboard_content()
        elif index == 1:
            client = ClientsPage(self.page, self)
            self.placeholder.content = client.build()
        elif index == 2:
            transporters = TransportersPage(self.page, self)
            self.placeholder.content = transporters.build()
        elif index == 3:
            destinations = DestinationsPage(self.page, self)
            self.placeholder.content = destinations.build()
        elif index == 4:
            orders = OrdersPage(self.page, self)
            self.placeholder.content = orders.build()
        elif index == 5:
            reports = ReportsPage(self.page, self)
            self.placeholder.content = reports.build()
        elif index == 6:
            profile = ProfilePage(self.page, self)
            self.placeholder.content = profile.build()
        elif index == 7:
            subscription = Subscription(self.page, self)
            self.placeholder.content = subscription.build()
        self.placeholder.update()     
            
    def got_to_profile(self, e):
        self.placeholder.content.clean()
        profile = ProfilePage(self.page, self)
        self.placeholder.content = profile.build()
        self.placeholder.update() 

    def _navigate_or_logout(self, index):
        if index == 8:  # Index of the "Logout" destination
            self._logout()
        else:
            self._navigate(index)

    def _logout(self):
        self.page.client_storage.remove("token")
        self.page.session.clear()
        self.page.go("/auth")

    def get_subscription(self):
        try:
            user_id = self.page.session.get("user_id")
            token = self.page.client_storage.get("token")
            headers = {"Authorization": f"Bearer {token}"}
            response = requests.get(f"{API_BASE_URL}/admin/subscriptions/{user_id}", headers=headers)      
            return response.json() if response.status_code == 200 else None
        except Exception as e:
            print("Error loading clients:", e)

    def get_current_subscription_plan(self):
        try:
            token = self.page.client_storage.get("token")
            headers = {"Authorization": f"Bearer {token}"}
            response = requests.get(f"{API_BASE_URL}/subscription/", headers=headers)
            #print(response.text)
            return response.json()[-1] if response.status_code == 200 else None
        except Exception as e:
            print("Error loading subscription:", e)
        
    def build(self):
        # Responsive behavior: hide logo in nav rail when window is short
        self.page.on_resize = self._on_resize
        current_height = self.page.height or 0
        self.logo_container.visible = current_height > 600
        self.status = {
            'active':'Active',
            'cancelled':'Cancelled',
            'expired':'Expired',
            'less_than_5_days':'Less than 5 days'
        }
        self.subscription = self.get_current_subscription_plan()

        if self.subscription:
            self.subscription_status_bottom = ft.Text(
                f'{self.status[self.subscription['status']] if self.subscription else "None"}',
                size=12,
                weight=ft.FontWeight.BOLD,
                color=ft.Colors.GREEN if self.subscription['status'] != 'expired' else ft.Colors.RED
            )
        else:
            self.subscription_status_bottom = ft.Text(
                f'{self.status[self.subscription['status']] if self.subscription else "None"}',
                size=12,
                weight=ft.FontWeight.BOLD,
                color=ft.Colors.RED
            )

        nav_rail = ft.NavigationRail(
            selected_index=0,
            label_type=ft.NavigationRailLabelType.ALL,
            on_change=lambda e: self._navigate_or_logout(e.control.selected_index),
            destinations=[
                ft.NavigationRailDestination(
                    icon=ft.Icons.DASHBOARD, label="Dashboard"
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.PEOPLE, label="Clients"
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.LOCAL_SHIPPING, label="Transporters"
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.LOCATION_ON, label="Address"
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.RECEIPT_LONG, label="Orders"
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.ASSESSMENT, label="Reports"
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.MANAGE_ACCOUNTS, label="Profile"
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.AUTORENEW, label="Subscription"
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.LOGOUT, label="Logout"
                )
            ],
            leading=self.logo_container,
            #bgcolor = ft.Colors.BLUE,
            
            trailing = ft.Column(
                [
                    ft.Text(
                        f'\nSubsctiption:',
                        size=12,
                    ),
                    self.subscription_status_bottom
                ],
                horizontal_alignment=ft.CrossAxisAlignment.CENTER
            )
        )

        self.placeholder.content = self._build_dashboard_content()

        return ft.Row(
            controls=[
                nav_rail,
                ft.VerticalDivider(),
                self.placeholder
            ],
            expand=True
        )

 