import flet as ft
from dbActions.orders import Orders
from dbActions.products import Products
from dbActions.company import Company
from dbActions.users import Users
from dbActions.fidelity_cards import FidelityCards
from dbActions.netopia import Netopia
from helpers.emails import send_gmail
from helpers.netopia import start_card_payment
import re

class Cart:
    def __init__(self, page: ft.Page):
        self.page = page
        self.user = self.page.session.get('user') 
        self.orders_manager = Orders()
        self.productsDB = Products()
        self.company_manager = Company()
        self.user_manager = Users()
        self.card_manager = FidelityCards()
        self.netopia_manager = Netopia()
        self.products = []
        self.is_second_address = None
        self.is_company = None
        self.pret_total = ft.Text("Pret total: 0", weight=ft.FontWeight.BOLD)
        self.delete_dialog = ft.AlertDialog(
            title=ft.Text("Stergeti?"),
            actions=[
                ft.FilledButton("Da", on_click=self.on_confirm_delete_btn_click),
                ft.FilledButton("Nu", on_click=self.on_cancel_delete_btn_click, bgcolor=ft.Colors.GREY)
            ]
        )
        
        self.on_hold_orders = self.orders_manager.get_on_hold_order(self.user['id'])
        if self.on_hold_orders:
            self.order_products = self.orders_manager.get_order_products(self.on_hold_orders['id'])
            
            for product in self.order_products:
                self.products.append(
                    {
                        'product':self.productsDB.get(product['prdouct_id']),
                        'quantity':product['quantity']
                    }
                )
        self.product_list = ft.ListView(
            controls=self.create_list(self.products, self.on_delete_product_click),
            spacing=10,
            expand=5
        )
        
        self.payment = ft.RadioGroup(
            content=ft.Row(
                [
                    ft.Radio(value="ramburs", label="Ramburs la curier"),
                    ft.Radio(value="plata_online_cu_cardul", label="Plata online cu cardul", disabled=True if self.user['email'] != 'user_de_test@gmail.com' else False),
                ]
            ),
            on_change=self.on_payment_value_change
        )
        self.payment.value = 'ramburs' if self.user['email'] != 'user_de_test@gmail.com' else None
        self.payment_message = ft.Text("")
        self.payment_redirect_button = ft.FilledButton(
            "Finalizeaza plata",
            visible=False,
        )
        self.error_message = ft.Text(
            color=ft.Colors.RED
        )

        self.confirm_dialog = ft.AlertDialog(
            title=ft.Text("Confirma"),
            actions=[
                ft.FilledButton(
                    "Da", 
                    on_click=self.on_confim_btn_click
                ),
                ft.FilledButton(
                    "Nu", 
                    on_click=self.on_cancel_btn_click,
                    bgcolor=ft.Colors.GREY
                )
            ]
        )

        self.all_orders = self.orders_manager.get_orders_for_user(self.page.session.get('user')['id'])
        self.all_orders = self.all_orders[::-1]
        self.orders_manager_list = ft.ListView(
            controls=self.create_history_list(self.all_orders),
            spacing=10,
            expand=True
        )
        self.user = self.page.session.get("user")
        self.company = self.company_manager.get_company(self.user['id'])
        prenume = ''
        if "@default.com" not in self.user['email']:
            if '~' in self.user['name']:
                prenume = self.user['name'].split('~')[0] 
        self.first_name = ft.TextField(
            label="Prenume",
            value=prenume
        )
        nume = ''
        if "@default.com" not in self.user['email']:
            if '~' in self.user['name']:
                nume = self.user['name'].split('~')[1] 
        self.last_name = ft.TextField(
            label="Nume",
            value=nume
        )

        self.email = ft.TextField(
            label="E-mail", 
            value=self.user['email'] if "@default.com" not in self.user['email'] else None, 
            read_only=True if "@default.com" not in self.user['email'] else False
        )
        self.phone = ft.TextField(
            label="Telefon", 
            value=self.user['phone'] if "@default.com" not in self.user['email'] else None
        )
        address = ''
        if self.user['address']:
            if "~" in self.user['address']:
                address = self.user['address'].split("~")[0].split("%")[1]
            else:
                address = self.user['address'].split("%")[1]
        self.address = ft.TextField(
            label="Strada si numar", 
            multiline=True, 
            min_lines=3, 
            max_lines=5, 
            value = address
        )
        city = ''
        if self.user['address']:
            if "~" in self.user['address']:
                city = self.user['address'].split("~")[0].split("%")[0]
            else:
                city = self.user['address'].split("%")[0]
        self.city = ft.TextField(
            label="Oras",
            value = city
        )

        self.company_name = ft.TextField(
            label="Denumire firma", 
            value=self.company['name'] if self.company else ''
        )
        self.vat = ft.TextField(
            label="CUI", 
            value=self.company['vat'] if self.company else ''
        )
        self.register_number = ft.TextField(
            label="Numar registru comert", 
            value=self.company['register_number'] if self.company else ''
        )
        self.company_address = ft.TextField(
            label="Sediu",  
            multiline=True, 
            min_lines=3, 
            max_lines=5,
            value=self.company['address'] if self.company else '')
        self.second_address_placeholder = ft.Column()
        self.second_address = ft.TextField(
                label="Adresa de livrare (str, nr, oras, judet)",
                multiline=True, 
                min_lines=3, 
                max_lines=5,
                value=self.user['address'].split("~")[1] if self.user['address'] and "~" in self.user['address'] and len(self.user['address'].split("~"))>1 else ''
            )
        self.second_address_placeholder =ft.Column()
        self.order_placeholder =ft.Column()

        if self.user['address'] and len(self.user['address'].split("~"))>1 :
            self.is_second_address = True
            self.second_address_placeholder.controls.append(self.second_address)
        if self.company:
            self.is_company = True
            self.order_placeholder.controls.append(self.company_name)
            self.order_placeholder.controls.append(self.vat)
            self.order_placeholder.controls.append(self.register_number)
            self.order_placeholder.controls.append(self.company_address)

        self.order_btn = ft.FilledButton(
            "Comanda",
            width=150,
            on_click=self.open_confirm_dialog
        )

        self.delivery_details = ft.Column(
            [
                ft.Text(
                    "Detaili de livrare",
                    weight=ft.FontWeight.BOLD
                ),
                self.first_name,
                self.last_name,
                self.email,
                self.phone,
                self.address,
                self.city,
                ft.Divider(),
                ft.Text("Adresa de livrare difera de adresa de domiciliu?", text_align=ft.TextAlign.CENTER),
                ft.Button("Adauga adresa livrare", width=500, on_click=self.on_second_address_btn_click),
                self.second_address_placeholder,
                ft.Divider(), 
                ft.Button("Doriti Factura?", width=500, on_click=self.on_order_btn_click),
                self.order_placeholder,

                ft.Text(
                    "Metoda de plata",
                    weight=ft.FontWeight.BOLD
                ),
                self.payment,
                ft.Text(
                    "Cost transport 17 lei.",
                    weight=ft.FontWeight.BOLD
                ),
                #self.payment_message,
                
                ft.Row([self.error_message],alignment=ft.MainAxisAlignment.CENTER),
                ft.Row(
                    [
                        self.order_btn
                    ],
                    alignment=ft.MainAxisAlignment.CENTER
                ),
                ft.Row([self.payment_redirect_button],alignment=ft.MainAxisAlignment.CENTER),  
            ],
            expand=5,
            alignment=ft.MainAxisAlignment.START
        )

        if self.page.width < 600:
            self.cart_placeholder = ft.Column(
                [
                    self.product_list,
                    self.delivery_details
                ]
            )
        else:
            self.cart_placeholder = ft.Row(
                [
                    self.product_list,
                    self.delivery_details
                ],
                vertical_alignment=ft.CrossAxisAlignment.START
            )
        self.order_list_placeholder = ft.Column()
        self.order_list_placeholder.controls.append(self.orders_manager_list)
            
        self.item_to_be_deleted = None

        self.page.add(self.delete_dialog)
        self.page.add(self.confirm_dialog)

        discount_cards= self.card_manager.get_all_fidelity_cards()
        _card_id = None
        for card in discount_cards:
            if card['phone_number'] == self.user['phone']:
                _card_id = card['card_id']
                break

        self.card_id = ft.Text(f"Card de reducere nr. {_card_id}" if _card_id else '', weight=ft.FontWeight.BOLD)

        self.update_cart_total()

        
        
    def on_second_address_btn_click(self, e):
        self.is_second_address = True
        self.second_address_placeholder.controls.append(self.second_address)
        self.second_address_placeholder.update()

    def on_order_btn_click(self, e):
        self.is_company = True
        self.order_placeholder.controls.append(self.company_name)
        self.order_placeholder.controls.append(self.vat)
        self.order_placeholder.controls.append(self.register_number)
        self.order_placeholder.controls.append(self.company_address)
        self.order_placeholder.update()

    def on_payment_value_change(self, e):
        print(e.data)
        if e.data == 'plata_online_cu_cardul':
            pass
        else:
            pass

    def get_order_products(self, id):
        products = self.orders_manager.get_order_products(id)
        total = 0
        
        all_products = []
        for product in products:
            item = self.productsDB.get(product['prdouct_id'])
            total += item['price']
            name = item['name']
            if name not in all_products:
                all_products.append(name)
        # try:
        #     self.pret_total.value = f'Pret total: {total+17}'
        #     self.pret_total.update()
        # except:
        #     pass
        return ft.Text(
            value=' '.join(all_products)
        )
    
    def update_cart_total(self):
        """Recalculate and update cart total (products + transport)."""
        if not self.on_hold_orders:
            self.pret_total.value = "Pret total: 0"
            return

        products = self.orders_manager.get_order_products(self.on_hold_orders['id'])
        total = 0
        for product in products:
            item = self.productsDB.get(product['prdouct_id'])
            total += item['price']

        shipping_cost = 17
        self.pret_total.value = f"Pret total: {total + shipping_cost}\n(include pret transport)"        

    def on_go_back_button_click(self, e):
        self.page.go("/")

    def create_list(self, items, on_click_handler):
        """Helper to create list items for a column."""
        return [
            ft.Container(
                content=ft.Row(
                    [
                        ft.Column(
                            [
                                ft.Row(
                                    [
                                        ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
                                        ft.Row(
                                            [
                                                ft.Image(
                                                    src=item['product']['image'], 
                                                    width=100,
                                                    height=100,
                                                    fit=ft.ImageFit.COVER,
                                                    border_radius=10
                                                ),
                                                ft.Column(
                                                    [
                                                        ft.Text(f"Denumire Produs: {item['product']['name']}", weight=ft.FontWeight.BOLD),
                                                        ft.Text(f"Cantitate: {item['quantity']}"),
                                                        ft.Text(f"Descriere: {item['product']['description']}", size=12 , color=ft.Colors.GREY),
                                                    ]
                                                )
                                            ]
                                        )
                                        
                                    ]
                                ),
                            ]
                        ),
                        ft.Row(
                            [
                                ft.FilledButton("Sterge",on_click=lambda e, id=item: on_click_handler(id), bgcolor=ft.Colors.RED),
                            ]
                        )
                        
                    ],
                    alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
                ),
                width=300,
                bgcolor=ft.Colors.BROWN_50,
                padding=10,
                border_radius=8,
                border = ft.border.all(1, ft.Colors.GREY),
            )
            for item in items
        ]
    
    def create_history_list(self, items):
        status_value = {
            'new':'Noua',
            'on_hold':'In asteptare',
            'in_progress': 'In lucru',
            'completed':'Complete'
        }
        return [
            ft.Container(
                content=ft.Column(
                    [

                        ft.Row(
                            [
                                ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
                                ft.Text(value="Numar comanda: "),
                                ft.Text(value=item['id'])
                            ]
                        ),
                        ft.Row(
                            [
                                ft.Text(
                                    value='Status: '
                                ),
                                ft.Text(
                                    value=status_value[item['status']]
                                )
                            ]
                        ),
                        ft.Row(
                            [
                                ft.Text(
                                    value='Produse: '
                                ),
                                self.get_order_products(item['id'])
                            ] 
                        )
                    ],
                    alignment=ft.MainAxisAlignment.START,
                ),
                width=300,
                bgcolor=ft.Colors.BROWN_50,
                padding=10,
                border_radius=8,
                border = ft.border.all(1, ft.Colors.GREY),
            )
            for item in items
        ]
  
    def on_delete_product_click(self, item):
        print('Delte item', item)
        
        self.page.open(self.delete_dialog)
        self.page.update()
        self.item_to_be_deleted = item['product']['id']

    def on_confirm_delete_btn_click(self, e):
        print("confirm delete item", self.item_to_be_deleted)
        #remove item
        self.orders_manager.remove_product_from_order(self.on_hold_orders['id'], self.item_to_be_deleted)
        #update list
        self.order_products = self.orders_manager.get_order_products(self.on_hold_orders['id'])
        self.products = []
        for product in self.order_products:
            self.products.append(
                {
                    'product':self.productsDB.get(product['prdouct_id']),
                    'quantity':product['quantity']
                }
            )
        self.product_list.controls.clear()
        self.product_list.controls = self.create_list(self.products, self.on_delete_product_click)
        self.product_list.update()

        self.item_to_be_deleted = None
        self.page.close(self.delete_dialog)

    def on_cancel_delete_btn_click(self, e):
        print("cancel item deletion: ", self.item_to_be_deleted)
        self.item_to_be_deleted = None
        self.page.close(self.delete_dialog)

    def open_confirm_dialog(self, e):
        print('open dialog')
        print(self.on_hold_orders)
        if self.on_hold_orders:
            self.error_message.value = ''
            self.error_message.update()
            self.page.open(self.confirm_dialog)
        else:
            self.error_message.value = "Nu aveti nici un produs in cos!"
            self.error_message.update()

    def on_cancel_btn_click(self, e):
        self.page.close(self.confirm_dialog)

    def check_second_address_inserted(self, address):
        if address is None or len(address)< 1:
            self.error_message.value = "Va rugam inserati adresa de livrare!"
            self.error_message.color = ft.Colors.RED
            self.error_message.update()
            print('Second address found')
            return True
        print('Second address not found')
        return False
    
    def check_company_data_inserted(self, company_name, vat, register_number, company_address):
        found = False
        if company_name is None or len(company_name)< 1:
            print("Comapny name not found")
            found = True
        if vat is None or len(vat)< 1:
            print("Vat not found")
            found = True
        if register_number is None or len(register_number)< 1:
            print("Register number not found")
            found = True
        if company_address is None or len(company_address)< 1:
            print("Company address not found")
            found = True
        if found: 
            self.error_message.value = "Toate campurile sunt obligatori!"
            self.error_message.color = ft.Colors.RED
            self.error_message.update()
        return found
    
    def check_inserted_user_data(self, username, phone, address, email, city):
        found = False
        if username is None or len(username)< 1:
            print('Username not found')
            found = True
        if phone is None or len(phone)< 1:
            print("Phone not found")
            found = True
        if address is None or len(address)< 1:
            print("Adress not found")
            found = True
        if city is None or len(city)< 1:
            print("City not found")
            found = True
        if email is None or len(email)<1:
            print("email not found")
            found = True
        if found: 
            self.error_message.value = "Toate campurile sunt obligatori!"
            self.error_message.color = ft.Colors.RED
            self.error_message.update()
        
        return found
    
    def check_email_is_valid(self, email):
        email_regex = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        if re.fullmatch(email_regex, email) is not None:
            self.error_message.value = ""
            self.error_message.update()
            return True
        else: 
            self.error_message.value = "Va rugam inserati un e-mail valid!"
            self.error_message.update()
            return False

    def create_update_user_details(self):
        username = self.first_name.value + "~" + self.last_name.value
        phone = self.phone.value
        address = self.city.value+"%"+self.address.value
        email = self.email.value
        
        if self.is_second_address:
            print("Second address has been selected (button click)")
            if self.check_second_address_inserted(self.second_address.value):
                return False
            address = self.city.value+"%"+self.address.value + '~' + self.second_address.value
        if self.check_inserted_user_data(username, phone, self.address.value, email, self.city.value): 
            return False
        
        if not self.check_email_is_valid(email):
            return False
        
        if '@default.com' in self.user['email']:
            print("User is default @default.com in name")
            try:
                user_id = self.user_manager.invite_user(
                    email, username, phone, address
                )
                self.user = self.user_manager.get(user_id)
                print("User invited")
                self.page.session.set("user", self.user)
                self.orders_manager.update_order_user_id(user_id, self.on_hold_orders['id'])
            except:
                print("Unable to create user, user already exists")
                self.error_message.value = "Exita deja un utilizator cu aceasta adresa de email!"
                return False
        else:
            self.user_manager.update_user_data(username, phone, address, self.user['id'])

        if self.is_company:
            print("Compani selected (company button has been pressed)")
            if self.check_company_data_inserted(self.company_name.value, self.vat.value, self.register_number.value, self.company_address.value):
                return
            if self.company:
                company['name'] = self.company_name.value
                company['vat'] = self.vat.value
                company['register_number'] = self.register_number.value
                company['address'] = self.company_address.value
                self.company_manager.update_company(company)
            else:
                company = {
                    'user_id' : self.user['id'],
                    'name': self.company_name.value,
                    'vat': self.vat.value,
                    'register_number': self.register_number.value,
                    'address': self.company_address.value
                }
                self.company_manager.add_company(company)
        if self.payment.value == None:
            self.error_message.value = "Va rugam selectati metoda de plata!"
            self.error_message.color = ft.Colors.RED
            self.error_message.update()
            return False
        return True
    
    def create_history(self):
        if '@default.com' not in self.user['email']:
            self.all_orders = self.orders_manager.get_orders_for_user(self.page.session.get('user')['id'])
            self.all_orders = self.all_orders[::-1]
            buffer = []
            for order in self.all_orders:
                if order['status'] != 'on_hold':
                    buffer.append(order)
            self.orders_manager_list.controls.clear()
            self.orders_manager_list.controls = self.create_history_list(buffer)
            self.orders_manager_list.update()

    def notify_admin_and_client(self):
        users = self.user_manager.get_all()
        admins = []
        for user in users:
            if user['role'] == 'admin':
                admins.append(user)
        for admin in admins:
            send_gmail(
                to_email=admin['email'],
                subject="Comanda noua pe tainagustului.ro",
                body=f'''
                    Ati primit o noua comanda de la {self.user['email']}.
                    Va rugam accesati wwww.tainagusutului.ro pentru detalii.
                '''
            )

            send_gmail(
                to_email=self.user['email'],
                subject="Multumim pentru comanda!",
                body=f'''
                    Buna ziua,

                    Comanda a fost primita si va fi livrata in cel mai scurt timp. 

                    Va multumim, 
                    Echipa tainagustului.ro
                '''
            )

    def save_order_ntp_id(self, order_id, netopia_id):
        self.netopia_manager.add_netopia_card(order_id, netopia_id)
    
    def online_pay(self, order_id):
        if self.payment.value == "plata_online_cu_cardul":
            print("The user seelected card payment")
            order_products = []
            products_ids = self.orders_manager.get_order_products(order_id)
            for prod in products_ids:
                p = self.productsDB.get(prod['prdouct_id'])
                order_products.append(
                    {
                        'name': p['name'],
                        'code': p['id'],
                        'category': p['category_id'],
                        'price': p['price'],
                        'vat': 0,
                    }
                )
            # Add transport (courier) cost as a separate product
            shipping_cost = 17.0
            order_products.append(
                {
                    'name': 'Transport curier',
                    'code': 'transport',
                    'category': 'transport',
                    'price': shipping_cost,
                    'vat': 0,
                }
            )

            # Calculate total amount including transport
            total_amount = sum(float(p['price']) for p in order_products)
            print(order_products)
            response = start_card_payment(
                order_id=order_id,
                amount=total_amount,
                currency='RON',
                description="Comanda noua",
                customer={
                    'email': self.email.value,
                    'phone': self.phone.value,
                    'firstName': self.first_name.value,
                    'lastName': self.last_name.value,
                    'city': self.city.value,
                    'country': 642,
                    'address': self.address.value,
                    'county': '',
                    'zipCode': ''
                },
                products=order_products
            )
            print(type(response))
            print(response)

            # Extract URL & ntpID from SDK response
            payment_url = response.payment['paymentURL']
            ntp_id = response.payment['ntpID']

            # 1) Persist mapping (VERY IMPORTANT for IPN/status reconciliation)
            if ntp_id:
                self.save_order_ntp_id(order_id, ntp_id)  # implement in your DB layer

            # 2) Show a button that opens the hosted payment page (iOS-safe)
            if payment_url:
                self.payment_redirect_button.url = payment_url
                self.payment_redirect_button.visible = True
                self.payment_redirect_button.text = "Finalizeaza plata"
                #self.payment_message.value = "Pentru a finaliza plata, apasati butonul de mai jos."
                #self.payment_message.update()
                self.payment_redirect_button.update()
                
            else:
                self.error_message.value = "Nu am primit URL-ul de plata."
                self.error_message.update()

    def on_confim_btn_click(self, e):
        self.error_message.color = ft.Colors.RED
        self.error_message.update()
        #create / update user details:
        print("Confirm button Selected ")
        self.page.close(self.confirm_dialog)
        if self.create_update_user_details():
            print('User details updated')
            order_id = self.on_hold_orders['id']
            self.orders_manager.update_order_status("new", self.on_hold_orders['id'])
            print('Order status is set to new')
            self.products = []
            self.on_hold_orders = self.orders_manager.get_on_hold_order(self.user['id'])
            if self.on_hold_orders:
                self.order_products = self.orders_manager.get_order_products(self.on_hold_orders['id'])
                
                for product in self.order_products:
                    self.products.append(
                        {
                            'product':self.productsDB.get(product['prdouct_id']),
                            'quantity':product['quantity']
                        }
                    )
            self.product_list.controls.clear()
            self.product_list.controls = self.create_list(self.products, self.on_delete_product_click)
            self.product_list.update()
            
            #hiostory
            self.create_history()

            if self.payment.value == "plata_online_cu_cardul":
                self.error_message.value = "Generam linul de plata, va rugam asteptati!"
                self.order_btn.visible = False
                self.order_btn.update()
            else:
                self.error_message.value = "Comanda a fost trimisa cu succes. Va multumim!"
            self.error_message.color = ft.Colors.GREEN
            self.error_message.update()

            #online pay
            self.online_pay(order_id)

            #notify admin
            self.notify_admin_and_client()

    def build(self):
        return ft.Container(
            content=ft.Column(
                [
                    ft.Row(
                        [
                            ft.Row(
                                [
                                    ft.Icon(
                                        ft.Icons.SHOPPING_CART_CHECKOUT,
                                        size=40,
                                    ),
                                    ft.Column(
                                        [
                                            self.pret_total,
                                            self.card_id,
                                            # ft.Text(
                                            #     "Produse adugate:",
                                            #     weight=ft.FontWeight.BOLD,
                                            #     size=15
                                            # ),    
                                        ]
                                    )
                                ]
                            ),
                            
                            ft.FilledButton(
                                text="Inapoi", 
                                icon=ft.Icons.ARROW_BACK,
                                on_click=self.on_go_back_button_click
                            )
                        ],
                        alignment=ft.MainAxisAlignment.SPACE_BETWEEN
                    ),
                    ft.Divider(),
                    self.cart_placeholder,
                    self.order_list_placeholder,
                    ft.Text()
                ],
                expand=True, 
                scroll=ft.ScrollMode.ADAPTIVE 
            ),
            expand=True,
            width=1000,
            padding=10
        )