from typing import List
from fastapi import APIRouter, Depends, HTTPException, status,BackgroundTasks
from datetime import date
from sqlalchemy.exc import IntegrityError
#db
from src.Service.companyService import CompanyService
from src.company_management.model import AppearanceThemeSettings, Attachment,  EmailNotificationSettings, IpAddress, Ticket
from src.core.database import get_db
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import delete, desc, func, select, update
from sqlalchemy.orm import selectinload

#external services
from src.external.email import transporter
#models
from src.models.company import Company
from src.models.company_user import User


#schemas
from .schemas import (
AddCompanyUser,
CompanyIpAddressSchema,
SettingsNotificationsSchema,
ThemeSchema,
TicketUSerSchema,
UpdateCompanyUser,UpdateTicketUSerSchema
)


#global deps

#auth utils
from src.auth.utils import pwd_context

#global utils
from src.common.utils import generate_password





class CompanyManagement(CompanyService):

   
    
    @staticmethod
    async def add_user_to_company(user_info:AddCompanyUser,company_id:str,db:AsyncSession):

        company = await CompanyManagement.get_company_by_id(company_id=company_id,db=db)

        stmt = select(User).where(User.email == user_info.user_email ).limit(1)
        result = await db.execute(stmt)
        is_user_exists = result.scalars().first()

        if is_user_exists:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="A user with this email exists."
            )
        
    
        
        system_generated_password = generate_password()

        new_user = User(
                full_name=user_info.full_name,
                email=user_info.user_email,
                department=user_info.user_department,
                role=user_info.user_role,
                hashed_password=pwd_context.hash(system_generated_password),
                company_name=company.company_name,
                company_id= company.id
            )
        

        db.add(new_user)
        await db.commit()               
        await db.refresh(new_user)      

        company.users_count += 1

        await db.commit()               

        print(new_user.full_name,"Added")
        print("system_generated_password", system_generated_password)
        logo_url = "https://FPnAInsights.mavenerp.in/assets/logo-transparent-png-CpxLVvxs.png"
        new_password = f'''
        <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Account Details - FPnAInsights</title>
  <script src="https://kit.fontawesome.com/your-fontawesome-kit.js" crossorigin="anonymous"></script>
</head>
<body style="background-color: #f9fafb; color: #1e293b; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; min-height: 100vh; margin: 0; padding: 1.5rem;">
  <div style="max-width: 800px; margin: 0 auto; background-color: #ffffff; box-shadow: 0 4px 12px rgba(0,0,0,0.08); border-radius: 12px; overflow: hidden; border: 1px solid #e5e7eb;">
    <!-- Header Strip -->
    <div style="height: 6px; background: linear-gradient(to right, #2563eb, #3b82f6);"></div>

    <!-- Main Content -->
    <div style="padding: 32px;">
      <!-- Logo and Header -->
      <div style="text-align: center; margin-bottom: 24px;">
        <img src="{logo_url}" alt="Logo" style="height: 48px; width: auto; margin-bottom: 16px;" />
        <h1 style="font-size: 24px; font-weight: 600; color: #111827; margin: 0 0 8px 0;">
          Welcome to Your Admin Account
        </h1>
        <p style="font-size: 14px; color: #6b7280; margin: 0; line-height: 1.5;">
          You've been granted administrator access to Formaven Group Global. Here are your secure login credentials:
        </p>
      </div>

      <!-- Credentials Section -->
      <div style="background-color: #f8fafc; border-radius: 8px; padding: 24px; margin-bottom: 24px;">
        <!-- Role and Password Side by Side -->
        <div style=" margin-bottom: 16px;">
          <!-- Role Section -->
          <div>
            <div style="font-size: 12px; font-weight: 600; color: #6b7280; text-transform: uppercase; margin-bottom: 8px; display: flex; align-items: center; gap: 6px;">
              <i class="fas fa-user-shield"></i> Role
            </div>
            <div style="padding: 12px; border-radius: 6px; background-color: #ecfdf5; color: #065f46; font-family: 'Courier New', monospace; font-size: 14px; border: 1px solid #d1fae5;">
              {new_user.role}
            </div>
          </div>

          <!-- Password Section -->
          <div>
            <div style="font-size: 12px; font-weight: 600; color: #6b7280; text-transform: uppercase; margin-bottom: 8px; display: flex; align-items: center; gap: 6px;">
              <i class="fas fa-key"></i> Temporary Password
            </div>
            <div style="padding: 12px; border-radius: 6px; background-color: #ecfdf5; color: #065f46; font-family: 'Courier New', monospace; font-size: 14px; border: 1px solid #d1fae5;">
              {system_generated_password}
            </div>
          </div>
        </div>

        <!-- Password Strength Indicator -->
        <div style="display: flex; align-items: center; gap: 8px; margin-top: 12px;">
          <div style="color: #15803d; font-size: 12px; display: flex; align-items: center; gap: 6px;">
            <i class="fas fa-shield-alt"></i> Secure auto-generated password
          </div>
          <div style="flex-grow: 1; display: flex; gap: 4px; margin-left: 8px;">
            <div style="flex: 1; height: 4px; background-color: #22c55e; border-radius: 2px;"></div>
            <div style="flex: 1; height: 4px; background-color: #22c55e; border-radius: 2px;"></div>
            <div style="flex: 1; height: 4px; background-color: #22c55e; border-radius: 2px;"></div>
            <div style="flex: 1; height: 4px; background-color: #22c55e; border-radius: 2px;"></div>
            <div style="flex: 1; height: 4px; background-color: #22c55e; border-radius: 2px;"></div>
          </div>
        </div>
      </div>

      <!-- Instructions -->
      <div style="background-color: #f8fafc; border-radius: 8px; padding: 24px; margin-bottom: 24px;">
        <h3 style="font-size: 16px; font-weight: 600; color: #111827; margin: 0 0 12px 0; display: flex; align-items: center; gap: 8px;">
          <i class="fas fa-info-circle"></i> Important Instructions
        </h3>
        <ul style="font-size: 14px; color: #4b5563; margin: 0; padding-left: 20px; line-height: 1.6;">
          <li style="margin-bottom: 8px;">Change your password immediately after first login</li>
          <li style="margin-bottom: 8px;">Do not share your credentials with anyone</li>
          <li style="margin-bottom: 8px;">Enable two-factor authentication for added security</li>
          <li>Contact support if you notice any suspicious activity</li>
        </ul>
      </div>

      <!-- Footer -->
      <div style="border-top: 1px solid #e5e7eb; padding-top: 24px; text-align: center;">
        <p style="font-size: 12px; color: #6b7280; margin: 0 0 8px 0;">
          If you're facing any issues, please contact:
          <a href="mailto:support@FPnAInsights.in" style="color: #2563eb; text-decoration: none; font-weight: 600;">support@FPnAInsights.in</a>
        </p>
        <p style="font-size: 12px; color: #6b7280; margin: 0;">
          © 2025 FPnAInsights. All rights reserved.
        </p>
      </div>
    </div>
  </div>
</body>
</html>
'''

        transporter.connect()
        transporter.send(user_info.user_email,
        "sending password"
        ,new_password)#f"user on boarding to for{user_info.user_email}",f"user on boarding to for{company.company_name} role:{user_info.user_role}, password: {system_generated_password}") 
        transporter.close()

        return {"message":"user added","user":new_user}

    async def delete_user(user_id:str,company_id:str,db:AsyncSession):

        try:
            user  = await CompanyManagement.get_companyuser_by_id(user_id,db)
            company = await CompanyManagement.get_company_by_id(company_id=company_id,db=db)

            if(user.company_id != company_id):

                raise HTTPException(
                        status_code=status.HTTP_404_NOT_FOUND,
                        detail="User not found"
                    )
            

            await db.delete(user)
            company.users_count = company.users_count - 1 

            await db.commit()

            user = {
              "name":user.full_name,
              "user_id":user.id  
            }

            return {"message":"user deleted","user":user}
        
        except HTTPException as e:
            raise e 
        
        except Exception as e:
            db.rollback()
            raise

    async def update_user(user_info:UpdateCompanyUser,company_id:str,db:AsyncSession):

        user = await CompanyManagement.get_companyuser_by_id(user_id= user_info.user_id, db=db)
        
            
        if(user_info.user_email):

            stmt = select(User).where(User.email == user_info.user_email).limit(1)
            result = await db.execute(stmt)
            existing_user_with_email = result.scalars().first()
            if not existing_user_with_email:
                user.email=user_info.user_email
            
            
        
        print("update user info",user.company_id,company_id)
        if user.company_id != company_id: # company level check 
            
            raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="User not found"
                )
        

        if user_info.full_name:
            user.full_name=user_info.full_name

        if user_info.user_department:

            user.department = user_info.user_department

        if user_info.user_role:
            user.role = user_info.user_role

        if user_info.reset_password:
            system_generated_password = generate_password()
            user.hashed_password = pwd_context.hash(system_generated_password)
            user.system_password_reset = False
            password_reset_message = "Password has been reset successfully."
        else:
            password_reset_message = None

        await db.commit()
        await db.refresh(user)

        #response model and return only the necessary fields
        user_response = {
            "user_id":user.id,
            "full_name":user.full_name,
            "user_email":user.email,
            "user_department":user.department,
            "user_role":user.role,
            "password":system_generated_password if password_reset_message else None

        }

        return {
            "detail": "User updated successfully" if not password_reset_message else password_reset_message,
            "user": user_response
        }
    
    @staticmethod
    async def get_company_users(company_id:str,db:AsyncSession):

        stmt = select(
        User.id,
        User.full_name,
        User.email,
        User.role,
        User.department,
        User.company_id,
        User.company_name,
        User.is_active,
        User.is_2FA_enabled,
        User.is_2FA_required,
        User.system_password_reset,
        User.created_at,
        User.updated_at,
        User.deleted_at,
        User.permissions,
        ).where(User.company_id == company_id)

        result = await db.execute(stmt)

        users = result.mappings().all()

        return {
            "users":users
            }
    
    async def company_user_activate_deactivate(company_id:str,user_id:str,db:AsyncSession):
        
        user = await CompanyManagement.get_companyuser_by_id(user_id= user_id,db = db)

        if(company_id != user.company_id):
            raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="user not found in company"
                )
        if(user.is_active):
            message ="user is deactivated"
            user.is_active = False
        else:
            message ="user is activated"
            user.is_active = True

                
        await db.commit()
        await db.refresh(user)

        return {
                "message": message,
                "user_name":user.full_name,
                "user_email":user.email,
                "user_status":user.is_active
                
                }


    async def set_company_theme(theme:ThemeSchema,company_id:str,db:AsyncSession):
        company= await CompanyManagement.get_company_by_id(company_id=company_id,db=db)
        if not company:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Company not found"
            )
        stm= select(AppearanceThemeSettings).where(AppearanceThemeSettings.company_id == company_id)
        result = await db.execute(stm)
        existing_theme = result.scalars().first()
        if existing_theme:
            # Update existing theme settings
            existing_theme.primary_color = theme.primary_color
            existing_theme.font_size = theme.font_size
            existing_theme.font_color = theme.font_color
            existing_theme.background_color = theme.background_color
            existing_theme.font_family = theme.font_family
            await db.commit()
            await db.refresh(existing_theme)
            
        else:
            theme_data=AppearanceThemeSettings(
                company_id=company_id,
                primary_color=theme.primary_color,
                font_size=theme.font_size,
                font_color=theme.font_color,
                background_color=theme.background_color,
                font_family=theme.font_family,
            )
            db.add(theme_data)
            await db.commit()
            await db.refresh(theme_data)
        #delattr(theme_data,"company_id")  # Remove company_id from the response if not needed
        return {
            "message": "Theme settings updated successfully",
            "theme": theme
        }
    async def get_company_theme(company_id:str,db:AsyncSession):
        #company=await CompanyManagement.get_compnay_info_by_id(company_id=company_id,db=db)
        smt=select(AppearanceThemeSettings).where(AppearanceThemeSettings.company_id==company_id).limit(1)
        result = await db.execute(smt)
        theme=result.scalars().first()
        if not theme:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail={
                    "error": "ThemeNotFound",
                    "message": "Theme settings not found for the company",
                    "default": True
                }
            )
        delattr(theme,"company_id")  # Remove company_id from the response if not needed
        return {
            "message": "Theme settings retrieved successfully",
            "theme": theme
        }
    async def set_company_ipaddress(company_id:str,ipaddress:str,db:AsyncSession):
            new_ip=IpAddress(allowed_ipaddress=ipaddress,company_id=company_id)    
            db.add(new_ip)
            try:
                await db.commit()
                await db.refresh(new_ip)
        
                return {
                    "message":"successfully stored"
                }
            except IntegrityError as e:
                await db.rollback()
                return {"detail":"this ip address is already in use"}
    
    async def delete_company_ipaddress(company_id:str,ipaddress:str,db:AsyncSession):
        smt=select(IpAddress).where(IpAddress.allowed_ipaddress==ipaddress)
        result = await db.execute(smt)
        ipaddress=result.scalars().first()
        if ipaddress:
            await db.delete(ipaddress)
            
            await db.commit()
            return {"message":"successfully deleted"}
        return {"message":"no record found"}
    async def get_company_ipaddress(company_id:str,db:AsyncSession):
        smt=select(IpAddress).where(IpAddress.company_id==company_id)
        result = await db.execute(smt)
        ipaddress=result.scalars().all()
        return {"message":"successfully retrieved","ipaddress":ipaddress}
   
    @staticmethod
    async def create_ticket(ticket:TicketUSerSchema,file_location:List[str],company_id:str,user_id:str,db:AsyncSession):
        '''
        create ticket in database
        args:
        ticket : ticket data
        company_id : id of the company
        user_id : id of the user
        email : email of the user
        db : database session
        returns:
        success message
        '''
        user=await CompanyManagement.get_companyuser_by_id(user_id=user_id,db=db)
        if not user:
            raise HTTPException(status_code=404,detail="user not found")
        try:
            #ticket=TicketUSerSchema().load(ticket)
            ticket_data=Ticket(company_id=company_id,user_id=user_id,email=user.email,
                            issue_type=ticket.issue_type,title=ticket.title,description=ticket.description,priority=ticket.priority,created_at=date.today())
            db.add(ticket_data)
            await db.commit()
            await db.refresh(ticket_data)

            # Now that `ticket.id` exists, generate ticket_id
            ticket_data.generate_ticket_id()
            await db.commit()
        
            for file in file_location:
                attachment = Attachment(ticket_id=ticket_data.id, file_path=file)
                db.add(attachment)
                await db.commit()
                await db.refresh(attachment)
        except Exception as e:
            await db.rollback()
            print(e)
            raise HTTPException(status_code=500, detail=str(e))
        #reset_link = f"https://example.com/reset-password/{encrypted_token}"

        # transporter.connect()
        # transporter.send(
        #     user.email,
        #     "Password Reset Request",
        #     f"Hi {user.full_name},\n\nClick the link below to reset your password:\n{reset_link}\n\nThis link will expire in 10 minutes."
        # )
        # transporter.close()
        return {"message":"ticket created"}
   
    @classmethod 
    async def get_ticket(cls,page,limit,
                         title:str,issuetype:str,priority:str,
                         company_id:str,db:AsyncSession):
        '''
        get ticket details by id
        args:
        ticket_id : id of the ticket
        db : database session
        returns:
        ticket details
        '''
        stmt=select(Ticket).where(Ticket.company_id==company_id)
        offset = (page - 1) * limit
        filter=[]
        if title:
                filter.append(Ticket.title.ilike(f"%{title}%"))
        if issuetype:
                filter.append(Ticket.issue_type == issuetype)
        if priority:
                filter.append(Ticket.priority == priority)
        
        if filter:
            stmt =stmt.filter(*filter)
         # Count total for pagination
        count_stmt = select(func.count()).select_from(stmt.subquery())
        total_result = await db.execute(count_stmt)
        total = total_result.scalar_one()

            
        smt=stmt.options(selectinload(Ticket.attachments)).order_by(desc(Ticket.created_at) , desc(Ticket.updated_at)).offset(offset).limit(limit)
        result=await db.execute(smt)
        fetched_tickets=result.scalars().all()
        total_pages = (total + limit - 1) // limit
        has_next = page * limit < total
        
        
        return {
            "tickets": fetched_tickets,
            "has_next": has_next,
            "total_pages": total_pages,
        }

  
      
    @staticmethod
    async def updateticket(ticketid:str,ticket_obj:UpdateTicketUSerSchema, file_location:list|str|None,db:AsyncSession):
        '''
        update ticket details
        args:
        TicketId : id of the ticket
        ticket_obj : ticket object to be updated
        file_location : file location of the attachment
        db : database session
        returns:
        updated ticket details
        '''
        

        try:
                ticket_obj1 = select(Ticket).options(selectinload(Ticket.attachments)).where(Ticket.ticket_id == ticketid)
                result=await db.execute(ticket_obj1)
                ticket= result.scalars().first()

                if not ticket:
                    raise HTTPException(status_code=404, detail="Ticket not found")

                if ticket.status == "Closed":
                    raise HTTPException(status_code=403, detail="Cannot edit a closed ticket")
                print(ticket_obj)
                # Update fields if provided
                if ticket_obj.issue_type :
                    
                    ticket.issue_type = ticket_obj.issue_type
                if ticket_obj.title :
                    print("title")
                    ticket.title = ticket_obj.title
                if ticket_obj.description :
                    print("description")
                    ticket.description = ticket_obj.description
                if ticket_obj.priority :
                    print("priority")
                    ticket.priority = ticket_obj.priority
                
                if file_location:
                    print("files")
                    ticket.attachments.clear()  # Clear previous attachments

                    if isinstance(file_location, list):
                        for path in file_location:
                            attachment = Attachment(file_path=path)
                            ticket.attachments.append(attachment)
                    elif isinstance(file_location, str):
                        attachment = Attachment(file_path=file_location)
                        ticket.attachments.append(attachment)
                    else:
                        raise ValueError(f"Invalid type for file_location: {type(file_location)}")

                # if file_location!=[]:
                # # Add attachments
                #     for file in file_location:
                #         attachment = Attachment(ticket_id=TicketId, file_path=file)
                #         db.add(attachment)

                await db.commit()  # Commit once after all changes
                await db.refresh(ticket)  # Refresh main object if needed
                return{"message": "Ticket updated successfully", "ticket": ticket}
        except Exception as e:
                await db.rollback()  
                print(e)
                raise HTTPException(status_code=500, detail=str(e))
    
        
    @staticmethod
    async def notificationsSettings(setting:SettingsNotificationsSchema,user_id:str,db:AsyncSession):
        '''
        send settings notifications to users based on the settings notification schema
        args:
        settings : alert notification settings schema
        user_id : id of the user
        return:
        list of alert notifications sent to the user
        '''
        try:
            user_id = user_id
            notification=select(EmailNotificationSettings).where(EmailNotificationSettings.user_id==user_id)
            result = await db.execute(notification)
            settings = result.scalars().first()
            if settings:
                if settings.transaction_alert:
                    # send email notification
                    notification.transaction_alert=setting.transaction_alert
                if settings.report_ready:
                    # send email notification
                    notification.report_ready=setting.report_ready
                if settings.system_update:
                    # send email notification
                    notification.system_update=setting.system_update
                if settings.weekly_summary:
                    # send email notification
                    notification.weekly_summary=setting.weekly_summary
                db.add(notification)
                await db.commit()
                return notification
            # Create a new alert notification
            notification = EmailNotificationSettings(
            user_id=user_id,
            transaction_alert=setting.transaction_alert,
            report_ready=setting.report_ready,
            system_update=setting.system_update,
            weekly_summary=setting.weekly_summary,
        )
            # Add the alert notification to the database
            db.add(notification)
            await db.commit()
            await db.refresh(notification)
            return {"message": "Alert notification sent successfully", "notification": notification}
        except Exception as e:
            await db.rollback()
            print(e)
            raise HTTPException(status_code=500, detail={
                "message": "Error sending alert notification",
            })
        
    @staticmethod
    async def get_notifications_Settings(user_id:str,db:AsyncSession):
        '''
        get all settings notifications for a user
        args:
        user_id : id of the user
        db : database session
        returns:
         notifications settings for the user
        '''
        try:
            
            stmt = select(EmailNotificationSettings).where(EmailNotificationSettings.user_id == str(user_id))
            result = await db.execute(stmt)
            notifications = result.scalars().all()
            return notifications
        except Exception as e:
                 print(e)
        except HTTPException as e:
            raise HTTPException(status_code=e.status_code, detail=e.detail)

    @staticmethod     
    async def getUserdetails(user_id:str,company_id,db:AsyncSession):
        user  = await CompanyManagement.get_companyuser_by_id(user_id,db)
        company = await CompanyManagement.get_company_by_id(company_id=company_id,db=db)

        if(user.company_id != company_id):

                raise HTTPException(
                        status_code=status.HTTP_404_NOT_FOUND,
                        detail="User not found"
                    )
            
        return { "user" : user,
                "company" : company
        }
            
