"""
e-conomic Export Service for Time Tracking Module
==================================================

🚨 KRITISK: Denne service skal respektere safety flags.
Eksporterer ordrer til e-conomic som draft orders.

Safety Flags:
- TIMETRACKING_ECONOMIC_READ_ONLY = True (default)
- TIMETRACKING_ECONOMIC_DRY_RUN = True (default)
"""

import logging
import json
from typing import Optional, Dict, Any

import aiohttp
from fastapi import HTTPException

from app.core.config import settings
from app.core.database import execute_query, execute_update, execute_query_single
from app.timetracking.backend.models import (
    TModuleEconomicExportRequest,
    TModuleEconomicExportResult
)
from app.timetracking.backend.audit import audit
from app.timetracking.backend.vtiger_sync import vtiger_service

logger = logging.getLogger(__name__)


class EconomicExportService:
    """
    e-conomic integration for Time Tracking Module.
    
    🔒 SAFETY-FIRST service - all writes controlled by flags.
    """
    
    def __init__(self):
        self.api_url = settings.ECONOMIC_API_URL
        self.app_secret_token = settings.ECONOMIC_APP_SECRET_TOKEN
        self.agreement_grant_token = settings.ECONOMIC_AGREEMENT_GRANT_TOKEN
        
        # Safety flags
        self.read_only = settings.TIMETRACKING_ECONOMIC_READ_ONLY
        self.dry_run = settings.TIMETRACKING_ECONOMIC_DRY_RUN
        self.export_type = settings.TIMETRACKING_EXPORT_TYPE
        
        # Log safety status
        if self.read_only:
            logger.warning("🔒 TIMETRACKING e-conomic READ-ONLY mode: Enabled")
        if self.dry_run:
            logger.warning("🏃 TIMETRACKING e-conomic DRY-RUN mode: Enabled")
        
        if not self.read_only:
            logger.error("⚠️ WARNING: TIMETRACKING e-conomic READ-ONLY disabled!")
    
    def _get_headers(self) -> Dict[str, str]:
        """Get e-conomic API headers"""
        return {
            'X-AppSecretToken': self.app_secret_token,
            'X-AgreementGrantToken': self.agreement_grant_token,
            'Content-Type': 'application/json'
        }
    
    def _check_write_permission(self, operation: str) -> bool:
        """
        Check om write operation er tilladt.
        
        Returns:
            True hvis operationen må udføres, False hvis blokeret
        """
        if self.read_only:
            logger.error(f"🚫 BLOCKED: {operation} - READ_ONLY mode enabled")
            return False
        
        if self.dry_run:
            logger.warning(f"🏃 DRY-RUN: {operation} - Would execute but not sending")
            return False
        
        logger.warning(f"⚠️ EXECUTING WRITE: {operation}")
        return True
    
    async def test_connection(self) -> bool:
        """Test e-conomic connection"""
        try:
            logger.info("🔍 Testing e-conomic connection...")
            
            async with aiohttp.ClientSession() as session:
                async with session.get(
                    f"{self.api_url}/self",
                    headers=self._get_headers(),
                    timeout=aiohttp.ClientTimeout(total=10)
                ) as response:
                    if response.status == 200:
                        logger.info("✅ e-conomic connection successful")
                        return True
                    else:
                        logger.error(f"❌ e-conomic connection failed: {response.status}")
                        return False
        
        except Exception as e:
            logger.error(f"❌ e-conomic connection error: {e}")
            return False
    
    async def check_draft_exists(self, draft_id: int) -> bool:
        """
        Tjek om en draft order stadig eksisterer i e-conomic.
        
        Args:
            draft_id: e-conomic draft order nummer
            
        Returns:
            True hvis draft findes, False hvis slettet eller ikke fundet
        """
        try:
            logger.info(f"🔍 Checking if draft {draft_id} exists in e-conomic...")
            
            async with aiohttp.ClientSession() as session:
                async with session.get(
                    f"{self.api_url}/orders/drafts/{draft_id}",
                    headers=self._get_headers(),
                    timeout=aiohttp.ClientTimeout(total=10)
                ) as response:
                    if response.status == 200:
                        logger.info(f"✅ Draft {draft_id} exists in e-conomic")
                        return True
                    elif response.status == 404:
                        logger.info(f"✅ Draft {draft_id} NOT found in e-conomic (deleted)")
                        return False
                    else:
                        error_text = await response.text()
                        logger.error(f"❌ e-conomic check failed ({response.status}): {error_text}")
                        raise Exception(f"e-conomic API error: {response.status}")
        
        except aiohttp.ClientError as e:
            logger.error(f"❌ e-conomic connection error: {e}")
            raise Exception(f"Kunne ikke forbinde til e-conomic: {str(e)}")
        except Exception as e:
            logger.error(f"❌ Draft check error: {e}")
            raise
    
    async def export_order(
        self,
        request: TModuleEconomicExportRequest,
        user_id: Optional[int] = None
    ) -> TModuleEconomicExportResult:
        """
        Eksporter ordre til e-conomic som draft order.
        
        Args:
            request: Export request med order_id
            user_id: ID på brugeren der eksporterer
            
        Returns:
            Export result med success status
        """
        try:
            # Hent ordre med linjer
            order_query = """
                SELECT o.*, c.name as customer_name, c.vtiger_id as customer_vtiger_id
                FROM tmodule_orders o
                JOIN tmodule_customers c ON o.customer_id = c.id
                WHERE o.id = %s
            """
            order = execute_query_single(order_query, (request.order_id,))
            
            if not order:
                raise HTTPException(status_code=404, detail="Order not found")
            
            # Check if order is posted (locked)
            if order['status'] == 'posted':
                raise HTTPException(
                    status_code=403,
                    detail=f"Ordre er bogført til e-conomic og kan ikke ændres. e-conomic ordre nr.: {order.get('economic_order_number')}"
                )
            
            # Check if already exported
            if order['economic_draft_id'] and not request.force:
                raise HTTPException(
                    status_code=400,
                    detail=f"Order already exported (draft ID: {order['economic_draft_id']}). Use force=true to re-export."
                )
            
            # Hent ordre-linjer
            lines_query = """
                SELECT * FROM tmodule_order_lines 
                WHERE order_id = %s 
                ORDER BY line_number
            """
            lines = execute_query(lines_query, (request.order_id,))
            
            if not lines:
                raise HTTPException(
                    status_code=400,
                    detail="Order has no lines"
                )
            
            # Log export start
            audit.log_export_started(
                order_id=request.order_id,
                user_id=user_id
            )
            
            # Check safety flags
            operation = f"Export order {request.order_id} to e-conomic"
            
            if not self._check_write_permission(operation):
                # Dry-run or read-only mode
                result = TModuleEconomicExportResult(
                    success=True,
                    dry_run=True,
                    order_id=request.order_id,
                    economic_draft_id=None,
                    economic_order_number=None,
                    message=f"DRY-RUN: Would export order {order['order_number']} to e-conomic",
                    details={
                        "order_number": order['order_number'],
                        "customer_name": order['customer_name'],
                        "total_amount": float(order['total_amount']),
                        "line_count": len(lines),
                        "read_only": self.read_only,
                        "dry_run": self.dry_run
                    }
                )
                
                # Log dry-run completion
                audit.log_export_completed(
                    order_id=request.order_id,
                    economic_draft_id=None,
                    economic_order_number=None,
                    dry_run=True,
                    user_id=user_id
                )
                
                return result
            
            # REAL EXPORT (kun hvis safety flags er disabled)
            logger.warning(f"⚠️ REAL EXPORT STARTING for order {request.order_id}")
            
            # Hent e-conomic customer number fra Hub customers via hub_customer_id
            customer_number_query = """
                SELECT c.economic_customer_number 
                FROM tmodule_customers tc
                LEFT JOIN customers c ON tc.hub_customer_id = c.id
                WHERE tc.id = %s
            """
            customer_data = execute_query_single(customer_number_query, (order['customer_id'],))
            
            if not customer_data or not customer_data.get('economic_customer_number'):
                # Check if customer is linked at all
                check_link = execute_query_single(
                    "SELECT hub_customer_id FROM tmodule_customers WHERE id = %s",
                    (order['customer_id'],)
                )
                if not check_link or not check_link.get('hub_customer_id'):
                    message = (
                        f"LOCAL-ONLY: Customer '{order['customer_name']}' er ikke linket til en Hub kunde. "
                        "Eksport til e-conomic er sprunget over."
                    )
                    logger.warning("⚠️ %s", message)

                    result = TModuleEconomicExportResult(
                        success=True,
                        dry_run=True,
                        order_id=request.order_id,
                        economic_draft_id=None,
                        economic_order_number=None,
                        message=message,
                        details={
                            "skipped_reason": "missing_hub_customer_link",
                            "order_number": order['order_number'],
                            "customer_name": order['customer_name'],
                            "read_only": self.read_only,
                            "dry_run": True,
                        }
                    )

                    audit.log_export_completed(
                        order_id=request.order_id,
                        economic_draft_id=None,
                        economic_order_number=None,
                        dry_run=True,
                        user_id=user_id,
                    )

                    return result
                else:
                    message = (
                        f"LOCAL-ONLY: Customer '{order['customer_name']}' mangler e-conomic kundenummer. "
                        "Eksport til e-conomic er sprunget over."
                    )
                    logger.warning("⚠️ %s", message)

                    result = TModuleEconomicExportResult(
                        success=True,
                        dry_run=True,
                        order_id=request.order_id,
                        economic_draft_id=None,
                        economic_order_number=None,
                        message=message,
                        details={
                            "skipped_reason": "missing_economic_customer_number",
                            "order_number": order['order_number'],
                            "customer_name": order['customer_name'],
                            "read_only": self.read_only,
                            "dry_run": True,
                        }
                    )

                    audit.log_export_completed(
                        order_id=request.order_id,
                        economic_draft_id=None,
                        economic_order_number=None,
                        dry_run=True,
                        user_id=user_id,
                    )

                    return result
            
            customer_number = customer_data['economic_customer_number']
            
            # 🔍 VALIDATE: Check if customer exists in e-conomic
            logger.info(f"🔍 Validating customer {customer_number} exists in e-conomic...")
            async with aiohttp.ClientSession() as session:
                async with session.get(
                    f"{self.api_url}/customers/{customer_number}",
                    headers=self._get_headers(),
                    timeout=aiohttp.ClientTimeout(total=10)
                ) as response:
                    if response.status == 404:
                        raise HTTPException(
                            status_code=400,
                            detail=f"Kunde '{order['customer_name']}' med e-conomic nummer '{customer_number}' findes ikke i e-conomic. Kontroller kundenummeret i Customers modulet."
                        )
                    elif response.status != 200:
                        logger.warning(f"⚠️ Could not validate customer: {response.status}")
                        # Continue anyway - might be network issue
            
            # 🔍 VALIDATE: Check if layout exists in e-conomic
            layout_number = settings.TIMETRACKING_ECONOMIC_LAYOUT
            logger.info(f"🔍 Validating layout {layout_number} exists in e-conomic...")
            async with aiohttp.ClientSession() as session:
                async with session.get(
                    f"{self.api_url}/layouts/{layout_number}",
                    headers=self._get_headers(),
                    timeout=aiohttp.ClientTimeout(total=10)
                ) as response:
                    if response.status == 404:
                        raise HTTPException(
                            status_code=400,
                            detail=f"Layout nummer '{layout_number}' findes ikke i e-conomic. Opdater TIMETRACKING_ECONOMIC_LAYOUT i .env filen med et gyldigt layout nummer fra e-conomic."
                        )
                    elif response.status != 200:
                        logger.warning(f"⚠️ Could not validate layout: {response.status}")
                        # Continue anyway - might be network issue
            
            # Build e-conomic draft order payload
            economic_payload = {
                "date": order['order_date'].isoformat() if hasattr(order['order_date'], 'isoformat') else str(order['order_date']),
                "currency": "DKK",
                "exchangeRate": 100,
                "otherReference": order['order_number'],  # Hub ordre nummer (TT-20251222-005)
                "customer": {
                    "customerNumber": customer_number
                },
                "recipient": {
                    "name": order['customer_name'],
                    "vatZone": {
                        "vatZoneNumber": 1  # Domestic Denmark
                    }
                },
                "paymentTerms": {
                    "paymentTermsNumber": 1  # Default payment terms
                },
                "layout": {
                    "layoutNumber": settings.TIMETRACKING_ECONOMIC_LAYOUT
                },
                "notes": {
                    "heading": "Tidsregistrering"
                },
                "lines": []
            }
            
            # Add notes if present
            if order.get('notes'):
                economic_payload['notes']['textLine1'] = order['notes']
            
            # Build order lines
            for idx, line in enumerate(lines, start=1):
                # Format: "CC0042. 3 timer 1200,- 3600 / Fejlsøgning / 27.05.2025 - Kontaktnavn"
                # Extract case number and title from existing description
                desc_parts = line['description'].split(' - ', 1)
                case_number = desc_parts[0] if desc_parts else ""
                case_title = desc_parts[1] if len(desc_parts) > 1 else line['description']
                
                # Build formatted description
                hours = float(line['quantity'])
                price = float(line['unit_price'])
                total = hours * price
                
                # Format date (Danish format DD.MM.YYYY)
                date_str = ""
                if line.get('time_date'):
                    time_date = line['time_date']
                    if isinstance(time_date, str):
                        from datetime import datetime
                        time_date = datetime.fromisoformat(time_date).date()
                    date_str = time_date.strftime("%d.%m.%Y")
                
                # Build description (case_number + task details)
                contact_part = f" - {line['case_contact']}" if line.get('case_contact') else ""
                travel_marker = " - (Udkørsel)" if line.get('is_travel') else ""
                formatted_desc = f"{case_number} / {case_title} / {date_str}{contact_part}{travel_marker}"
                
                economic_line = {
                    "lineNumber": idx,
                    "sortKey": idx,
                    "description": formatted_desc,
                    "quantity": hours,
                    "unitNetPrice": price,
                    "product": {
                        "productNumber": line.get('product_number') or settings.TIMETRACKING_ECONOMIC_PRODUCT
                    },
                    "unit": {
                        "unitNumber": 2  # timer (unit 2 in e-conomic)
                    }
                }
                
                # Add discount if present
                if line.get('discount_percentage'):
                    economic_line['discountPercentage'] = float(line['discount_percentage'])
                
                economic_payload['lines'].append(economic_line)
            
            logger.info(f"📤 Sending to e-conomic: {json.dumps(economic_payload, indent=2, default=str)}")
            
            # Call e-conomic API
            async with aiohttp.ClientSession() as session:
                async with session.post(
                    f"{self.api_url}/orders/drafts",
                    headers=self._get_headers(),
                    json=economic_payload,
                    timeout=aiohttp.ClientTimeout(total=30)
                ) as response:
                    response_text = await response.text()
                    
                    if response.status not in [200, 201]:
                        logger.error(f"❌ e-conomic export failed: {response.status}")
                        logger.error(f"Response: {response_text}")
                        logger.error(f"Payload: {json.dumps(economic_payload, indent=2, default=str)}")
                        
                        # Try to parse error message
                        try:
                            error_data = json.loads(response_text)
                            error_msg = error_data.get('message', response_text)
                            
                            # Parse detailed validation errors if present
                            if 'errors' in error_data:
                                error_details = []
                                for entity, entity_errors in error_data['errors'].items():
                                    if isinstance(entity_errors, dict) and 'errors' in entity_errors:
                                        for err in entity_errors['errors']:
                                            field = err.get('propertyName', entity)
                                            msg = err.get('errorMessage', err.get('message', 'Unknown'))
                                            error_details.append(f"{field}: {msg}")
                                if error_details:
                                    error_msg = '; '.join(error_details)
                        except:
                            error_msg = response_text
                        
                        # Log failed export
                        audit.log_export_failed(
                            order_id=request.order_id,
                            error=error_msg,
                            user_id=user_id
                        )
                        
                        raise HTTPException(
                            status_code=response.status,
                            detail=f"e-conomic API error: {error_msg}"
                        )
                    
                    result_data = await response.json()
                    logger.info(f"✅ e-conomic response: {json.dumps(result_data, indent=2, default=str)}")
                    
                    # e-conomic returnerer orderNumber direkte for draft orders
                    order_number = result_data.get('orderNumber') or result_data.get('draftOrderNumber')
                    economic_draft_id = int(order_number) if order_number else None
                    economic_order_number = str(order_number) if order_number else None
                    
                    # Update order med e-conomic IDs og status = posted (bogført)
                    execute_update(
                        """UPDATE tmodule_orders 
                           SET economic_draft_id = %s, 
                               economic_order_number = %s,
                               exported_at = CURRENT_TIMESTAMP,
                               exported_by = %s,
                               status = 'posted'
                           WHERE id = %s""",
                        (economic_draft_id, economic_order_number, user_id, request.order_id)
                    )
                    
                    # Marker time entries som billed og opdater billed_via_thehub_id
                    execute_update(
                        """UPDATE tmodule_times
                           SET status = 'billed',
                               billed_via_thehub_id = %s
                           WHERE id IN (
                               SELECT UNNEST(time_entry_ids) 
                               FROM tmodule_order_lines 
                               WHERE order_id = %s
                           )""",
                        (request.order_id, request.order_id)
                    )
                    
                    # Hent vTiger IDs for tidsregistreringerne
                    vtiger_ids_query = """
                        SELECT t.vtiger_id
                        FROM tmodule_times t
                        WHERE t.id IN (
                            SELECT UNNEST(time_entry_ids)
                            FROM tmodule_order_lines
                            WHERE order_id = %s
                        )
                    """
                    vtiger_time_records = execute_query(vtiger_ids_query, (request.order_id,))
                    vtiger_ids = [r['vtiger_id'] for r in vtiger_time_records]
                    
                    # Opdater Timelog records i vTiger med Hub ordre ID
                    if vtiger_ids:
                        logger.info(f"📝 Updating {len(vtiger_ids)} timelogs in vTiger with Hub order {request.order_id}...")
                        try:
                            vtiger_update_result = await vtiger_service.update_timelog_billed(
                                vtiger_ids=vtiger_ids,
                                hub_order_id=request.order_id
                            )
                            logger.info(f"✅ vTiger update: {vtiger_update_result}")
                        except Exception as vtiger_error:
                            # Don't fail export if vTiger update fails - just log it
                            logger.error(f"⚠️ Could not update vTiger timelogs: {vtiger_error}")
                    
                    # Log successful export
                    audit.log_export_completed(
                        order_id=request.order_id,
                        economic_draft_id=economic_draft_id,
                        economic_order_number=economic_order_number,
                        dry_run=False,
                        user_id=user_id
                    )
                    
                    logger.info(f"✅ Exported order {request.order_id} → e-conomic draft {economic_draft_id}")
                    
                    return TModuleEconomicExportResult(
                        success=True,
                        dry_run=False,
                        order_id=request.order_id,
                        economic_draft_id=economic_draft_id,
                        economic_order_number=economic_order_number,
                        message=f"Successfully exported to e-conomic draft {economic_draft_id}",
                        details=result_data
                    )
        
        except HTTPException:
            raise
        except Exception as e:
            logger.error(f"❌ Error exporting order: {e}")
            
            # Log failed export
            audit.log_export_failed(
                order_id=request.order_id,
                error=str(e),
                user_id=user_id
            )
            
            raise HTTPException(status_code=500, detail=str(e))


# Singleton instance
economic_service = EconomicExportService()
