import requests
from typing import List, Dict, Optional
from datetime import datetime
from stamps.models import Stamp
from .base import IPayrollAdapter


class NetvisorAdapter(IPayrollAdapter):
    """Adapter for Netvisor payroll system"""
    
    def transform_stamp_data(self, stamps: List[Stamp], employee_id: str) -> Dict:
        """
        Transform Stamp data to Netvisor format
        """
        entries = []
        
        for stamp in stamps:
            # Parse duration
            hours = self._parse_duration(stamp.duration) if stamp.duration else 0.0
            
            # Get project mapping
            cost_center = None
            if stamp.project:
                cost_center = self.get_project_mapping(str(stamp.project.id))
            
            # Map stamp_function to paycode (default to 'REGULAR' if not mapped)
            paycode = self._map_stamp_function_to_paycode(stamp.stamp_function)
            
            entry = {
                "date": stamp.date.isoformat(),
                "hours": hours,
                "cost_center": cost_center,
                "task_code": stamp.task.code if stamp.task and hasattr(stamp.task, 'code') else None,
                "description": stamp.description or "",
                "paycode": paycode
            }
            entries.append(entry)
        
        return {
            "timesheet": {
                "employee_id": employee_id,
                "entries": entries
            }
        }
    
    def submit_timesheet(
        self, 
        employee_id: str, 
        period_start: datetime, 
        period_end: datetime,
        timesheet_data: Dict
    ) -> Dict:
        """
        Submit timesheet to Netvisor API
        """
        try:
            # Netvisor API endpoint for timesheet submission
            url = f"{self.api_endpoint}/timesheet/submit"
            
            payload = {
                "employee_id": employee_id,
                "period_start": period_start.isoformat(),
                "period_end": period_end.isoformat(),
                **timesheet_data
            }
            
            headers = {
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            }
            
            response = requests.post(url, json=payload, headers=headers, timeout=30)
            
            if response.status_code == 200:
                data = response.json()
                return {
                    'success': True,
                    'reference_id': data.get('reference_id', ''),
                    'message': 'Timesheet submitted successfully',
                    'errors': []
                }
            else:
                return {
                    'success': False,
                    'reference_id': '',
                    'message': f'API returned status {response.status_code}',
                    'errors': [response.text]
                }
        except requests.exceptions.RequestException as e:
            return {
                'success': False,
                'reference_id': '',
                'message': f'Network error: {str(e)}',
                'errors': [str(e)]
            }
        except Exception as e:
            return {
                'success': False,
                'reference_id': '',
                'message': f'Unexpected error: {str(e)}',
                'errors': [str(e)]
            }
    
    def validate_credentials(self) -> bool:
        """
        Validate Netvisor API credentials
        """
        try:
            url = f"{self.api_endpoint}/auth/validate"
            headers = {
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            }
            
            response = requests.get(url, headers=headers, timeout=10)
            return response.status_code == 200
        except Exception:
            return False
    
    def get_employee_mapping(self, user_id: str) -> Optional[str]:
        """
        This should be implemented by the service layer using EmployeeMapping model
        For now, return None as this requires database access
        """
        return None
    
    def get_project_mapping(self, project_id: str) -> Optional[str]:
        """
        This should be implemented by the service layer using ProjectMapping model
        For now, return None as this requires database access
        """
        return None
    
    def _map_stamp_function_to_paycode(self, stamp_function: str) -> str:
        """
        Map internal stamp_function to Netvisor paycode
        Default mapping - can be extended with configuration
        """
        mapping = {
            'W1': 'REGULAR',
            'W2': 'OVERTIME',
            'F1': 'VACATION',
            'F2': 'SICK',
        }
        return mapping.get(stamp_function, 'REGULAR')

