"""
Mock API Layer for Voice Agent
Simulates database with JSON storage - easy to swap with real DB
"""

from fastapi import FastAPI, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
from datetime import datetime, timedelta
from enum import Enum
import json
import os
from pathlib import Path

app = FastAPI(title="Credable Voice Agent API", version="1.0.0")

# CORS for frontend
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Data storage path
DATA_DIR = Path("./data")
DATA_DIR.mkdir(exist_ok=True)

# Models
class LoanStatus(str, Enum):
    ACTIVE = "active"
    PAID = "paid"
    DEFAULTED = "defaulted"
    PENDING = "pending"

class PaymentStatus(str, Enum):
    COMPLETED = "completed"
    PENDING = "pending"
    FAILED = "failed"

class UserProfile(BaseModel):
    customer_id: str
    phone: str
    name: str
    language_preference: str = "swahili"
    country: str = "TZ"  # TZ, KE, UG, MZ
    created_at: datetime
    credit_score: Optional[int] = None
    total_loans: int = 0
    active_loans: int = 0

class Loan(BaseModel):
    loan_id: str
    customer_id: str
    phone: str
    principal: float
    interest_rate: float
    total_amount: float
    disbursed_amount: float
    outstanding_balance: float
    status: LoanStatus
    disbursement_date: datetime
    due_date: datetime
    product_type: str  # "emergency", "business", "school_fees"
    payment_frequency: str  # "daily", "weekly", "monthly"

class Payment(BaseModel):
    payment_id: str
    loan_id: str
    customer_id: str
    phone: str
    amount: float
    payment_date: datetime
    status: PaymentStatus
    payment_method: str  # "mpesa", "airtel_money", "tigopesa"
    reference: str

class OutboundCallRequest(BaseModel):
    phone: str
    campaign_type: str  # "payment_reminder", "loan_offer", "survey"
    scheduled_time: Optional[datetime] = None
    priority: str = "normal"  # "high", "normal", "low"
    metadata: Dict[str, Any] = {}

# Storage helpers
class DataStore:
    """Simple JSON-based storage - easy to swap with real DB"""
    
    @staticmethod
    def _get_file_path(entity: str) -> Path:
        return DATA_DIR / f"{entity}.json"
    
    @staticmethod
    def load(entity: str) -> List[Dict]:
        """Load data from JSON file"""
        file_path = DataStore._get_file_path(entity)
        if not file_path.exists():
            return []
        with open(file_path, 'r') as f:
            return json.load(f)
    
    @staticmethod
    def save(entity: str, data: List[Dict]):
        """Save data to JSON file"""
        file_path = DataStore._get_file_path(entity)
        with open(file_path, 'w') as f:
            json.dump(data, f, indent=2, default=str)
    
    @staticmethod
    def find_one(entity: str, **criteria) -> Optional[Dict]:
        """Find single record matching criteria"""
        data = DataStore.load(entity)
        for record in data:
            if all(record.get(k) == v for k, v in criteria.items()):
                return record
        return None
    
    @staticmethod
    def find_many(entity: str, **criteria) -> List[Dict]:
        """Find all records matching criteria"""
        data = DataStore.load(entity)
        results = []
        for record in data:
            if all(record.get(k) == v for k, v in criteria.items()):
                results.append(record)
        return results

# Initialize with sample data
def init_sample_data():
    """Initialize sample data for testing"""
    
    # Sample users
    users = [
        {
            "customer_id": "CUST001",
            "phone": "+255712345678",
            "name": "John Mwangi",
            "language_preference": "swahili",
            "country": "TZ",
            "created_at": "2024-01-15T10:00:00",
            "credit_score": 750,
            "total_loans": 5,
            "active_loans": 1
        },
        {
            "customer_id": "CUST002",
            "phone": "+254722123456",
            "name": "Mary Wanjiku",
            "language_preference": "swahili",
            "country": "KE",
            "created_at": "2024-03-20T14:30:00",
            "credit_score": 680,
            "total_loans": 3,
            "active_loans": 2
        }
    ]
    
    # Sample loans
    loans = [
        {
            "loan_id": "LOAN001",
            "customer_id": "CUST001",
            "phone": "+255712345678",
            "principal": 500000.00,
            "interest_rate": 15.0,
            "total_amount": 575000.00,
            "disbursed_amount": 500000.00,
            "outstanding_balance": 150000.00,
            "status": "active",
            "disbursement_date": "2025-12-01T09:00:00",
            "due_date": "2026-02-28T23:59:59",
            "product_type": "business",
            "payment_frequency": "weekly"
        },
        {
            "loan_id": "LOAN002",
            "customer_id": "CUST002",
            "phone": "+254722123456",
            "principal": 200000.00,
            "interest_rate": 12.0,
            "total_amount": 224000.00,
            "disbursed_amount": 200000.00,
            "outstanding_balance": 224000.00,
            "status": "active",
            "disbursement_date": "2026-01-10T10:00:00",
            "due_date": "2026-03-10T23:59:59",
            "product_type": "emergency",
            "payment_frequency": "monthly"
        }
    ]
    
    # Sample payments
    payments = [
        {
            "payment_id": "PAY001",
            "loan_id": "LOAN001",
            "customer_id": "CUST001",
            "phone": "+255712345678",
            "amount": 50000.00,
            "payment_date": "2026-01-05T14:20:00",
            "status": "completed",
            "payment_method": "mpesa",
            "reference": "QA123XYZ456"
        },
        {
            "payment_id": "PAY002",
            "loan_id": "LOAN001",
            "customer_id": "CUST001",
            "phone": "+255712345678",
            "amount": 75000.00,
            "payment_date": "2026-01-12T11:15:00",
            "status": "completed",
            "payment_method": "mpesa",
            "reference": "QB456ABC789"
        }
    ]
    
    # Save sample data
    if not DataStore.load("users"):
        DataStore.save("users", users)
    if not DataStore.load("loans"):
        DataStore.save("loans", loans)
    if not DataStore.load("payments"):
        DataStore.save("payments", payments)

# API Endpoints

@app.on_event("startup")
async def startup():
    """Initialize sample data on startup"""
    init_sample_data()
    print("✅ Mock API initialized with sample data")

@app.get("/")
async def root():
    return {
        "service": "Credable Voice Agent API",
        "version": "1.0.0",
        "status": "operational"
    }

# User Profile APIs
@app.get("/api/v1/users/profile")
async def get_user_profile(phone: str) -> UserProfile:
    """Get user profile by phone number"""
    user = DataStore.find_one("users", phone=phone)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return UserProfile(**user)

@app.get("/api/v1/users/{customer_id}")
async def get_user_by_id(customer_id: str) -> UserProfile:
    """Get user profile by customer ID"""
    user = DataStore.find_one("users", customer_id=customer_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return UserProfile(**user)

# Loan APIs
@app.get("/api/v1/loans/active")
async def get_active_loans(phone: str) -> List[Loan]:
    """Get all active loans for a phone number"""
    loans = DataStore.find_many("loans", phone=phone, status="active")
    return [Loan(**loan) for loan in loans]

@app.get("/api/v1/loans/history")
async def get_loan_history(phone: str) -> List[Loan]:
    """Get complete loan history for a phone number"""
    loans = DataStore.find_many("loans", phone=phone)
    return [Loan(**loan) for loan in loans]

@app.get("/api/v1/loans/{loan_id}")
async def get_loan(loan_id: str) -> Loan:
    """Get specific loan details"""
    loan = DataStore.find_one("loans", loan_id=loan_id)
    if not loan:
        raise HTTPException(status_code=404, detail="Loan not found")
    return Loan(**loan)

@app.get("/api/v1/loans/{loan_id}/balance")
async def get_loan_balance(loan_id: str) -> Dict[str, Any]:
    """Get current balance for a loan"""
    loan = DataStore.find_one("loans", loan_id=loan_id)
    if not loan:
        raise HTTPException(status_code=404, detail="Loan not found")
    
    return {
        "loan_id": loan["loan_id"],
        "principal": loan["principal"],
        "total_amount": loan["total_amount"],
        "outstanding_balance": loan["outstanding_balance"],
        "amount_paid": loan["total_amount"] - loan["outstanding_balance"],
        "due_date": loan["due_date"],
        "days_remaining": (datetime.fromisoformat(loan["due_date"].replace('Z', '')) - datetime.now()).days
    }

# Payment APIs
@app.get("/api/v1/payments/recent")
async def get_recent_payments(phone: str, limit: int = 10) -> List[Payment]:
    """Get recent payments for a phone number"""
    payments = DataStore.find_many("payments", phone=phone)
    # Sort by date descending
    payments.sort(key=lambda x: x["payment_date"], reverse=True)
    return [Payment(**p) for p in payments[:limit]]

@app.get("/api/v1/payments/loan/{loan_id}")
async def get_loan_payments(loan_id: str) -> List[Payment]:
    """Get all payments for a specific loan"""
    payments = DataStore.find_many("payments", loan_id=loan_id)
    return [Payment(**p) for p in payments]

@app.post("/api/v1/payments/schedule")
async def schedule_payment(
    phone: str,
    loan_id: str,
    amount: float,
    payment_date: datetime
) -> Dict[str, Any]:
    """Schedule a future payment"""
    # Verify loan exists
    loan = DataStore.find_one("loans", loan_id=loan_id)
    if not loan:
        raise HTTPException(status_code=404, detail="Loan not found")
    
    # Create payment schedule entry
    schedule_id = f"SCH{datetime.now().strftime('%Y%m%d%H%M%S')}"
    
    return {
        "schedule_id": schedule_id,
        "loan_id": loan_id,
        "amount": amount,
        "scheduled_date": payment_date,
        "status": "scheduled"
    }

# Call Management APIs
@app.post("/api/v1/calls/outbound")
async def create_outbound_call(request: OutboundCallRequest) -> Dict[str, Any]:
    """Create outbound call request"""
    # Verify user exists
    user = DataStore.find_one("users", phone=request.phone)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    
    call_id = f"CALL{datetime.now().strftime('%Y%m%d%H%M%S')}"
    
    # Load existing calls
    calls = DataStore.load("outbound_calls")
    
    # Create new call request
    call_data = {
        "call_id": call_id,
        "phone": request.phone,
        "customer_id": user["customer_id"],
        "campaign_type": request.campaign_type,
        "scheduled_time": request.scheduled_time or datetime.now() + timedelta(minutes=5),
        "priority": request.priority,
        "status": "scheduled",
        "metadata": request.metadata,
        "created_at": datetime.now()
    }
    
    calls.append(call_data)
    DataStore.save("outbound_calls", calls)
    
    return {
        "call_id": call_id,
        "status": "scheduled",
        "message": f"Outbound call scheduled for {request.phone}"
    }

@app.get("/api/v1/calls/outbound/pending")
async def get_pending_calls() -> List[Dict[str, Any]]:
    """Get all pending outbound calls"""
    calls = DataStore.load("outbound_calls")
    pending = [c for c in calls if c["status"] == "scheduled"]
    return pending

@app.patch("/api/v1/calls/{call_id}/status")
async def update_call_status(call_id: str, status: str) -> Dict[str, Any]:
    """Update call status"""
    calls = DataStore.load("outbound_calls")
    
    for call in calls:
        if call["call_id"] == call_id:
            call["status"] = status
            call["updated_at"] = datetime.now()
            DataStore.save("outbound_calls", calls)
            return {"call_id": call_id, "status": status}
    
    raise HTTPException(status_code=404, detail="Call not found")

# Analytics APIs
@app.get("/api/v1/analytics/customer/{phone}")
async def get_customer_analytics(phone: str) -> Dict[str, Any]:
    """Get comprehensive customer analytics"""
    user = DataStore.find_one("users", phone=phone)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    
    loans = DataStore.find_many("loans", phone=phone)
    payments = DataStore.find_many("payments", phone=phone)
    
    total_borrowed = sum(loan["principal"] for loan in loans)
    total_paid = sum(payment["amount"] for payment in payments if payment["status"] == "completed")
    outstanding = sum(loan["outstanding_balance"] for loan in loans if loan["status"] == "active")
    
    return {
        "customer_id": user["customer_id"],
        "phone": phone,
        "name": user["name"],
        "total_loans": len(loans),
        "active_loans": len([l for l in loans if l["status"] == "active"]),
        "total_borrowed": total_borrowed,
        "total_paid": total_paid,
        "outstanding_balance": outstanding,
        "payment_history_count": len(payments),
        "credit_score": user.get("credit_score"),
        "last_payment_date": max((p["payment_date"] for p in payments), default=None) if payments else None
    }

if __name__ == "__main__":
    import uvicorn
    print("🚀 Starting Credable Voice Agent Mock API...")
    print("📊 Data storage: ./data/")
    print("🌐 API docs: http://localhost:8000/docs")
    uvicorn.run(app, host="0.0.0.0", port=8000)
