# app/services/drive_service.py
from googleapiclient.discovery import build
from google.oauth2 import service_account
from googleapiclient.http import MediaFileUpload
from flask import current_app
import os
from datetime import datetime
from ..models.contract import Contract
from ..models.user import User

class ContractDriveService:
    def __init__(self):
        self.scopes = ['https://www.googleapis.com/auth/drive']
        self.credentials_path = 'app/config/drive_credentials.json'
        self.service = self._build_service()
        
        # Corporate folder structure configuration
        self.root_contracts_folder = 'YOUR_CONTRACTS_FOLDER_ID'  # Update with actual folder ID
        self.executed_folder_name = '2.3 Executed (Signed)'
        self.in_progress_folder_name = '2.2 In-Progress'
        
    def _build_service(self):
        """Build Google Drive API service with service account"""
        try:
            if os.path.exists(self.credentials_path):
                credentials = service_account.Credentials.from_service_account_file(
                    self.credentials_path, scopes=self.scopes
                )
                return build('drive', 'v3', credentials=credentials)
            else:
                current_app.logger.warning("Drive credentials not found")
                return None
        except Exception as e:
            current_app.logger.error(f"Drive service setup failed: {str(e)}")
            return None

    def _generate_corporate_filename(self, contract, version="01"):
        """Generate filename according to corporate naming convention: YYYY-MM-DD__Counterparty__Contract_Agreement__v01.pdf"""
        try:
            # Extract contract metadata
            contract_date = contract.created_at or datetime.utcnow()
            date_str = contract_date.strftime('%Y-%m-%d')
            
            # Get counterparty name (contractor name)
            contractor = User.query.get(contract.contractor_id)
            if contractor:
                # Clean counterparty name for filename (remove special chars)
                counterparty = ''.join(c for c in contractor.first_name + contractor.last_name if c.isalnum())
                if not counterparty:  # Fallback if name cleaning fails
                    counterparty = f"Contractor_{contract.contractor_id}"
            else:
                counterparty = f"Contractor_{contract.contractor_id}"
            
            # Generate filename with corporate convention
            filename = f"{date_str}__{counterparty}__Contract_Agreement__v{version}.pdf"
            
            current_app.logger.info(f"Generated corporate filename: {filename}")
            return filename
            
        except Exception as e:
            current_app.logger.error(f"Filename generation failed: {str(e)}")
            # Fallback to basic naming
            return f"Contract_{contract.id}_Signed_v{version}.pdf"

    def _ensure_folder_structure(self, year=None):
        """Ensure proper folder structure exists: /2. Contracts/2.3 Executed (Signed)/[YEAR]/"""
        try:
            if not self.service:
                return None
                
            # Find or create the executed folder
            executed_folder_id = self._find_or_create_folder(
                self.executed_folder_name, 
                self.root_contracts_folder
            )
            
            if not executed_folder_id:
                current_app.logger.error("Failed to create/find executed contracts folder")
                return None
            
            # If year is specified, create/find year subfolder
            if year:
                year_folder_id = self._find_or_create_folder(
                    str(year), 
                    executed_folder_id
                )
                return year_folder_id
            
            return executed_folder_id
            
        except Exception as e:
            current_app.logger.error(f"Folder structure creation failed: {str(e)}")
            return None

    def _find_or_create_folder(self, folder_name, parent_folder_id):
        """Find existing folder or create new one"""
        try:
            # Search for existing folder
            query = f"name='{folder_name}' and '{parent_folder_id}' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false"
            results = self.service.files().list(q=query, fields='files(id, name)').execute()
            folders = results.get('files', [])
            
            if folders:
                current_app.logger.info(f"Found existing folder: {folder_name}")
                return folders[0]['id']
            
            # Create new folder if not found
            folder_metadata = {
                'name': folder_name,
                'parents': [parent_folder_id],
                'mimeType': 'application/vnd.google-apps.folder'
            }
            
            folder = self.service.files().create(
                body=folder_metadata,
                fields='id'
            ).execute()
            
            current_app.logger.info(f"Created new folder: {folder_name}")
            return folder.get('id')
            
        except Exception as e:
            current_app.logger.error(f"Folder creation/search failed for {folder_name}: {str(e)}")
            return None

    def _check_version_increment(self, filename, folder_id):
        """Check if file exists and increment version if needed"""
        try:
            base_name = filename.replace('.pdf', '').rsplit('__v', 1)[0]
            
            # Search for existing files with same base name
            query = f"name contains '{base_name}' and '{folder_id}' in parents and trashed=false"
            results = self.service.files().list(q=query, fields='files(id, name)').execute()
            files = results.get('files', [])
            
            if not files:
                return filename  # No existing files, use original
            
            # Find highest version number
            highest_version = 0
            for file in files:
                try:
                    if '__v' in file['name']:
                        version_part = file['name'].split('__v')[-1].replace('.pdf', '')
                        version_num = int(version_part)
                        highest_version = max(highest_version, version_num)
                except (ValueError, IndexError):
                    continue
            
            # Increment version
            new_version = highest_version + 1
            new_filename = f"{base_name}__v{new_version:02d}.pdf"
            
            current_app.logger.info(f"Version incremented to: {new_filename}")
            return new_filename
            
        except Exception as e:
            current_app.logger.error(f"Version checking failed: {str(e)}")
            return filename  # Return original on error

    def upload_signed_contract(self, pdf_path, contract_id):
        """Upload signed contract PDF to corporate folder structure with proper naming"""
        if not self.service:
            current_app.logger.error("Drive service not available")
            return None
            
        try:
            # Get contract details
            contract = Contract.query.get(contract_id)
            if not contract:
                current_app.logger.error(f"Contract {contract_id} not found")
                return None
            
            # Only upload fully signed contracts to executed folder
            if not contract.is_fully_signed():
                current_app.logger.warning(f"Contract {contract_id} not fully signed, skipping upload to executed folder")
                return None
            
            # Get contract year for folder organization
            contract_year = contract.created_at.year if contract.created_at else datetime.utcnow().year
            
            # Ensure proper folder structure exists
            target_folder_id = self._ensure_folder_structure(year=contract_year)
            if not target_folder_id:
                current_app.logger.error("Failed to create target folder structure")
                return None
            
            # Generate corporate-compliant filename
            filename = self._generate_corporate_filename(contract)
            
            # Check for version conflicts and increment if needed
            final_filename = self._check_version_increment(filename, target_folder_id)
            
            # Upload file with corporate metadata
            file_metadata = {
                'name': final_filename,
                'parents': [target_folder_id],
                'description': f'Executed contract for Contract ID: {contract_id}, Contractor: {contract.contractor_id}, Worker: {contract.worker_id}'
            }
            
            media = MediaFileUpload(pdf_path, mimetype='application/pdf')
            file = self.service.files().create(
                body=file_metadata,
                media_body=media,
                fields='id,webViewLink,name'
            ).execute()
            
            current_app.logger.info(f"Successfully uploaded contract {contract_id} as {final_filename} to Drive")
            return {
                'file_id': file.get('id'),
                'web_view_link': file.get('webViewLink'),
                'filename': file.get('name'),
                'folder_path': f"{self.executed_folder_name}/{contract_year}/"
            }
            
        except Exception as e:
            current_app.logger.error(f"Drive upload failed for contract {contract_id}: {str(e)}")
            return None

    def upload_draft_contract(self, pdf_path, contract_id):
        """Upload draft contract to in-progress folder"""
        if not self.service:
            return None
            
        try:
            contract = Contract.query.get(contract_id)
            if not contract:
                return None
            
            # Find or create in-progress folder
            in_progress_folder_id = self._find_or_create_folder(
                self.in_progress_folder_name, 
                self.root_contracts_folder
            )
            
            if not in_progress_folder_id:
                return None
            
            filename = self._generate_corporate_filename(contract, version="DRAFT")
            filename = filename.replace('__vDRAFT.pdf', '__DRAFT.pdf')
            
            file_metadata = {
                'name': filename,
                'parents': [in_progress_folder_id],
                'description': f'Draft contract for Contract ID: {contract_id}'
            }
            
            media = MediaFileUpload(pdf_path, mimetype='application/pdf')
            file = self.service.files().create(
                body=file_metadata,
                media_body=media,
                fields='id,webViewLink,name'
            ).execute()
            
            current_app.logger.info(f"Uploaded draft contract {contract_id} to in-progress folder")
            return {
                'file_id': file.get('id'),
                'web_view_link': file.get('webViewLink'),
                'filename': file.get('name'),
                'folder_path': f"{self.in_progress_folder_name}/"
            }
            
        except Exception as e:
            current_app.logger.error(f"Draft upload failed: {str(e)}")
            return None
