"""
Test data factories for creating consistent test data in the Zoho Projects SDK tests.
"""

import random
import string
from datetime import datetime, timedelta
from typing import Any, Dict, Optional


def generate_random_string(length: int = 10) -> str:
    """Generate a random string of specified length."""
    return "".join(random.choices(string.ascii_letters + string.digits, k=length))


def create_test_project_data(
    project_id: Optional[str] = None,
    name: Optional[str] = None,
    description: str = "Test project description",
    status: str = "active",
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
) -> Dict[str, Any]:
    """Create test data for a project."""
    if project_id is None:
        project_id = generate_random_string(12)
    if name is None:
        name = f"Test Project {generate_random_string(8)}"
    if start_date is None:
        start_date = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
    if end_date is None:
        end_date = (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d")

    return {
        "project_id": project_id,
        "name": name,
        "description": description,
        "status": status,
        "start_date": start_date,
        "end_date": end_date,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_task_data(
    task_id: Optional[str] = None,
    name: Optional[str] = None,
    description: str = "Test task description",
    status: str = "not_started",
    priority: str = "medium",
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
    project_id: Optional[str] = None,
    assignee_id: Optional[str] = None,
) -> Dict[str, Any]:
    """Create test data for a task."""
    if task_id is None:
        task_id = generate_random_string(12)
    if name is None:
        name = f"Test Task {generate_random_string(8)}"
    if start_date is None:
        start_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
    if end_date is None:
        end_date = (datetime.now() + timedelta(days=7)).strftime("%Y-%m-%d")
    if project_id is None:
        project_id = generate_random_string(12)
    if assignee_id is None:
        assignee_id = generate_random_string(12)

    return {
        "task_id": task_id,
        "name": name,
        "description": description,
        "status": status,
        "priority": priority,
        "start_date": start_date,
        "end_date": end_date,
        "project_id": project_id,
        "assignee_id": assignee_id,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_issue_data(
    issue_id: Optional[str] = None,
    title: Optional[str] = None,
    description: str = "Test issue description",
    status: str = "open",
    priority: str = "high",
    severity: str = "medium",
    project_id: Optional[str] = None,
    assignee_id: Optional[str] = None,
) -> Dict[str, Any]:
    """Create test data for an issue."""
    if issue_id is None:
        issue_id = generate_random_string(12)
    if title is None:
        title = f"Test Issue {generate_random_string(8)}"
    if project_id is None:
        project_id = generate_random_string(12)
    if assignee_id is None:
        assignee_id = generate_random_string(12)

    return {
        "issue_id": issue_id,
        "title": title,
        "description": description,
        "status": status,
        "priority": priority,
        "severity": severity,
        "project_id": project_id,
        "assignee_id": assignee_id,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_user_data(
    user_id: Optional[str] = None,
    email: Optional[str] = None,
    name: Optional[str] = None,
    role: str = "user",
    status: str = "active",
) -> Dict[str, Any]:
    """Create test data for a user."""
    if user_id is None:
        user_id = generate_random_string(12)
    if email is None:
        email = f"user_{generate_random_string(8)}@example.com"
    if name is None:
        name = f"Test User {generate_random_string(6)}"

    return {
        "user_id": user_id,
        "email": email,
        "name": name,
        "role": role,
        "status": status,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_client_data(
    client_id: Optional[str] = None,
    name: Optional[str] = None,
    email: Optional[str] = None,
    phone: Optional[str] = None,
    website: Optional[str] = None,
) -> Dict[str, Any]:
    """Create test data for a client."""
    if client_id is None:
        client_id = generate_random_string(12)
    if name is None:
        name = f"Test Client {generate_random_string(8)}"
    if email is None:
        email = f"client_{generate_random_string(8)}@example.com"
    if phone is None:
        phone = (
            f"+1-{random.randint(100, 999)}-"
            f"{random.randint(100, 999)}-{random.randint(1000, 9999)}"
        )
    if website is None:
        website = f"https://www.{generate_random_string(8)}.com"

    return {
        "client_id": client_id,
        "name": name,
        "email": email,
        "phone": phone,
        "website": website,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_contact_data(
    contact_id: Optional[str] = None,
    first_name: Optional[str] = None,
    last_name: Optional[str] = None,
    email: Optional[str] = None,
    phone: Optional[str] = None,
    client_id: Optional[str] = None,
) -> Dict[str, Any]:
    """Create test data for a contact."""
    if contact_id is None:
        contact_id = generate_random_string(12)
    if first_name is None:
        first_name = f"TestFirst{generate_random_string(6)}"
    if last_name is None:
        last_name = f"TestLast{generate_random_string(6)}"
    if email is None:
        email = f"contact_{generate_random_string(8)}@example.com"
    if phone is None:
        phone = (
            f"+1-{random.randint(100, 999)}-"
            f"{random.randint(100, 999)}-{random.randint(1000, 9999)}"
        )
    if client_id is None:
        client_id = generate_random_string(12)

    return {
        "contact_id": contact_id,
        "first_name": first_name,
        "last_name": last_name,
        "email": email,
        "phone": phone,
        "client_id": client_id,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_portal_data(
    portal_id: Optional[str] = None,
    name: Optional[str] = None,
    description: str = "Test portal description",
) -> Dict[str, Any]:
    """Create test data for a portal."""
    if portal_id is None:
        portal_id = generate_random_string(12)
    if name is None:
        name = f"Test Portal {generate_random_string(8)}"

    return {
        "portal_id": portal_id,
        "name": name,
        "description": description,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_role_data(
    role_id: Optional[str] = None,
    name: Optional[str] = None,
    description: str = "Test role description",
) -> Dict[str, Any]:
    """Create test data for a role."""
    if role_id is None:
        role_id = generate_random_string(12)
    if name is None:
        name = f"Test Role {generate_random_string(8)}"

    return {
        "role_id": role_id,
        "name": name,
        "description": description,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_tag_data(
    tag_id: Optional[str] = None,
    name: Optional[str] = None,
    color: str = "#FF0000",
) -> Dict[str, Any]:
    """Create test data for a tag."""
    if tag_id is None:
        tag_id = generate_random_string(12)
    if name is None:
        name = f"Test Tag {generate_random_string(8)}"

    return {
        "tag_id": tag_id,
        "name": name,
        "color": color,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_tasklist_data(
    tasklist_id: Optional[str] = None,
    name: Optional[str] = None,
    description: str = "Test tasklist description",
    project_id: Optional[str] = None,
    status: str = "active",
) -> Dict[str, Any]:
    """Create test data for a tasklist."""
    if tasklist_id is None:
        tasklist_id = generate_random_string(12)
    if name is None:
        name = f"Test Tasklist {generate_random_string(8)}"
    if project_id is None:
        project_id = generate_random_string(12)

    return {
        "tasklist_id": tasklist_id,
        "name": name,
        "description": description,
        "project_id": project_id,
        "status": status,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_timelog_data(
    timelog_id: Optional[str] = None,
    task_id: Optional[str] = None,
    user_id: Optional[str] = None,
    hours: float = 1.5,
    minutes: int = 30,
    log_date: Optional[str] = None,
    description: str = "Test timelog description",
) -> Dict[str, Any]:
    """Create test data for a timelog."""
    if timelog_id is None:
        timelog_id = generate_random_string(12)
    if task_id is None:
        task_id = generate_random_string(12)
    if user_id is None:
        user_id = generate_random_string(12)
    if log_date is None:
        log_date = datetime.now().strftime("%Y-%m-%d")

    return {
        "timelog_id": timelog_id,
        "task_id": task_id,
        "user_id": user_id,
        "hours": hours,
        "minutes": minutes,
        "log_date": log_date,
        "description": description,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_comment_data(
    comment_id: Optional[str] = None,
    content: str = "Test comment content",
    author_id: Optional[str] = None,
    entity_id: Optional[str] = None,
    entity_type: str = "task",
) -> Dict[str, Any]:
    """Create test data for a comment."""
    if comment_id is None:
        comment_id = generate_random_string(12)
    if author_id is None:
        author_id = generate_random_string(12)
    if entity_id is None:
        entity_id = generate_random_string(12)

    return {
        "comment_id": comment_id,
        "content": content,
        "author_id": author_id,
        "entity_id": entity_id,
        "entity_type": entity_type,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_attachment_data(
    attachment_id: Optional[str] = None,
    name: Optional[str] = None,
    size: int = 1024,
    url: str = "https://example.com/test_attachment.pdf",
    entity_id: Optional[str] = None,
    entity_type: str = "task",
) -> Dict[str, Any]:
    """Create test data for an attachment."""
    if attachment_id is None:
        attachment_id = generate_random_string(12)
    if name is None:
        name = f"test_attachment_{generate_random_string(8)}.pdf"
    if entity_id is None:
        entity_id = generate_random_string(12)

    return {
        "attachment_id": attachment_id,
        "name": name,
        "size": size,
        "url": url,
        "entity_id": entity_id,
        "entity_type": entity_type,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_baseline_data(
    baseline_id: Optional[str] = None,
    name: Optional[str] = None,
    project_id: Optional[str] = None,
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
    description: str = "Test baseline description",
) -> Dict[str, Any]:
    """Create test data for a baseline."""
    if baseline_id is None:
        baseline_id = generate_random_string(12)
    if name is None:
        name = f"Test Baseline {generate_random_string(8)}"
    if project_id is None:
        project_id = generate_random_string(12)
    if start_date is None:
        start_date = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
    if end_date is None:
        end_date = (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d")

    return {
        "baseline_id": baseline_id,
        "name": name,
        "project_id": project_id,
        "start_date": start_date,
        "end_date": end_date,
        "description": description,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_business_hours_data(
    business_hours_id: Optional[str] = None,
    name: Optional[str] = None,
    start_time: str = "09:00",
    end_time: str = "17:00",
    timezone: str = "UTC",
) -> Dict[str, Any]:
    """Create test data for business hours."""
    if business_hours_id is None:
        business_hours_id = generate_random_string(12)
    if name is None:
        name = f"Test Business Hours {generate_random_string(8)}"

    return {
        "business_hours_id": business_hours_id,
        "name": name,
        "start_time": start_time,
        "end_time": end_time,
        "timezone": timezone,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_event_data(
    event_id: Optional[str] = None,
    title: Optional[str] = None,
    description: str = "Test event description",
    start_time: Optional[str] = None,
    end_time: Optional[str] = None,
    project_id: Optional[str] = None,
) -> Dict[str, Any]:
    """Create test data for an event."""
    if event_id is None:
        event_id = generate_random_string(12)
    if title is None:
        title = f"Test Event {generate_random_string(8)}"
    if start_time is None:
        start_time = (datetime.now() + timedelta(hours=1)).strftime(
            "%Y-%m-%dT%H:%M:%SZ"
        )
    if end_time is None:
        end_time = (datetime.now() + timedelta(hours=2)).strftime("%Y-%m-%dT%H:%M:%SZ")
    if project_id is None:
        project_id = generate_random_string(12)

    return {
        "event_id": event_id,
        "title": title,
        "description": description,
        "start_time": start_time,
        "end_time": end_time,
        "project_id": project_id,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_milestone_data(
    milestone_id: Optional[str] = None,
    name: Optional[str] = None,
    description: str = "Test milestone description",
    project_id: Optional[str] = None,
    target_date: Optional[str] = None,
    status: str = "not_started",
) -> Dict[str, Any]:
    """Create test data for a milestone."""
    if milestone_id is None:
        milestone_id = generate_random_string(12)
    if name is None:
        name = f"Test Milestone {generate_random_string(8)}"
    if project_id is None:
        project_id = generate_random_string(12)
    if target_date is None:
        target_date = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")

    return {
        "milestone_id": milestone_id,
        "name": name,
        "description": description,
        "project_id": project_id,
        "target_date": target_date,
        "status": status,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_phase_data(
    phase_id: Optional[str] = None,
    name: Optional[str] = None,
    description: str = "Test phase description",
    project_id: Optional[str] = None,
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
    status: str = "not_started",
) -> Dict[str, Any]:
    """Create test data for a phase."""
    if phase_id is None:
        phase_id = generate_random_string(12)
    if name is None:
        name = f"Test Phase {generate_random_string(8)}"
    if project_id is None:
        project_id = generate_random_string(12)
    if start_date is None:
        start_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
    if end_date is None:
        end_date = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")

    return {
        "phase_id": phase_id,
        "name": name,
        "description": description,
        "project_id": project_id,
        "start_date": start_date,
        "end_date": end_date,
        "status": status,
        "created_time": datetime.now().isoformat(),
        "modified_time": datetime.now().isoformat(),
    }


def create_test_api_response(data: Any, status_code: int = 200) -> Dict[str, Any]:
    """Create a test API response structure."""
    return {
        "data": data,
        "status_code": status_code,
        "success": status_code < 300,
        "message": "Success" if status_code < 300 else "Error",
    }


def create_test_error_response(
    message: str = "An error occurred",
    status_code: int = 400,
    error_code: str = "GENERAL_ERROR",
) -> Dict[str, Any]:
    """Create a test error response structure."""
    return {
        "message": message,
        "status_code": status_code,
        "error_code": error_code,
        "success": False,
    }
