package com.tt.honeyDue.models

import com.tt.honeyDue.data.DataManager
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
 * User reference for task-related responses - matching Go API TaskUserResponse
 */
@Serializable
data class TaskUserResponse(
    val id: Int,
    val username: String,
    val email: String,
    @SerialName("first_name") val firstName: String = "",
    @SerialName("last_name") val lastName: String = ""
) {
    val displayName: String
        get() = when {
            firstName.isNotBlank() && lastName.isNotBlank() -> "$firstName $lastName"
            firstName.isNotBlank() -> firstName
            lastName.isNotBlank() -> lastName
            else -> username
        }
}

/**
 * Task response matching Go API TaskResponse
 */
@Serializable
data class TaskResponse(
    val id: Int,
    @SerialName("residence_id") val residenceId: Int,
    @SerialName("created_by_id") val createdById: Int,
    @SerialName("created_by") val createdBy: TaskUserResponse? = null,
    @SerialName("assigned_to_id") val assignedToId: Int? = null,
    @SerialName("assigned_to") val assignedTo: TaskUserResponse? = null,
    val title: String,
    val description: String = "",
    @SerialName("category_id") val categoryId: Int? = null,
    val category: TaskCategory? = null,
    @SerialName("priority_id") val priorityId: Int? = null,
    val priority: TaskPriority? = null,
    @SerialName("in_progress") val inProgress: Boolean = false,
    @SerialName("frequency_id") val frequencyId: Int? = null,
    val frequency: TaskFrequency? = null,
    @SerialName("custom_interval_days") val customIntervalDays: Int? = null, // For "Custom" frequency, user-specified days
    @SerialName("due_date") val dueDate: String? = null,
    @SerialName("next_due_date") val nextDueDate: String? = null, // For recurring tasks, updated after each completion
    @SerialName("estimated_cost") val estimatedCost: Double? = null,
    @SerialName("actual_cost") val actualCost: Double? = null,
    @SerialName("contractor_id") val contractorId: Int? = null,
    @SerialName("is_cancelled") val isCancelled: Boolean = false,
    @SerialName("is_archived") val isArchived: Boolean = false,
    @SerialName("parent_task_id") val parentTaskId: Int? = null,
    // Backlink to the TaskTemplate this task was spawned from (onboarding
    // suggestion or browse catalog). Null for user-created custom tasks.
    @SerialName("template_id") val templateId: Int? = null,
    @SerialName("completion_count") val completionCount: Int = 0,
    @SerialName("kanban_column") val kanbanColumn: String? = null, // Which kanban column this task belongs to
    // Note: Go API does not return completions inline with TaskResponse.
    // Completions are fetched separately via the completions endpoint.
    // This field defaults to emptyList() and is only populated client-side after a separate fetch.
    val completions: List<TaskCompletionResponse> = emptyList(),
    @SerialName("created_at") val createdAt: String,
    @SerialName("updated_at") val updatedAt: String
) {
    // Helper for backwards compatibility with old code
    val archived: Boolean get() = isArchived

    // Aliases for backwards compatibility with UI code expecting old field names
    val residence: Int get() = residenceId

    // Helper to get created by username
    val createdByUsername: String get() = createdBy?.displayName ?: ""

    // Computed properties for UI compatibility - resolves from cache if not embedded in response
    // This allows the API to skip Preloading these lookups for performance
    val categoryName: String? get() = category?.name ?: DataManager.getTaskCategory(categoryId)?.name
    val categoryDescription: String? get() = category?.description ?: DataManager.getTaskCategory(categoryId)?.description
    val frequencyName: String? get() = frequency?.name ?: DataManager.getTaskFrequency(frequencyId)?.name
    val frequencyDisplayName: String? get() = frequency?.displayName ?: DataManager.getTaskFrequency(frequencyId)?.displayName
    val frequencyDaySpan: Int? get() = frequency?.days ?: DataManager.getTaskFrequency(frequencyId)?.days
    val priorityName: String? get() = priority?.name ?: DataManager.getTaskPriority(priorityId)?.name
    val priorityDisplayName: String? get() = priority?.displayName ?: DataManager.getTaskPriority(priorityId)?.displayName

    // Effective due date: use nextDueDate if set (for recurring tasks), otherwise use dueDate
    val effectiveDueDate: String? get() = nextDueDate ?: dueDate

    // Fields that don't exist in Go API - return null/default
    val nextScheduledDate: String? get() = nextDueDate  // Now we have this from the API
    val showCompletedButton: Boolean get() = true // Always show complete button since status is now just in_progress boolean
    val daySpan: Int? get() = frequency?.days ?: DataManager.getTaskFrequency(frequencyId)?.days
    val notifyDays: Int? get() = null  // Not in Go API
}

/**
 * Task completion response matching Go API TaskCompletionResponse
 */
@Serializable
data class TaskCompletionResponse(
    val id: Int,
    @SerialName("task_id") val taskId: Int,
    @SerialName("completed_by") val completedBy: TaskUserResponse? = null,
    @SerialName("completed_at") val completedAt: String,
    val notes: String = "",
    @SerialName("actual_cost") val actualCost: Double? = null,
    val rating: Int? = null,
    val images: List<TaskCompletionImage> = emptyList(),
    @SerialName("created_at") val createdAt: String,
    @SerialName("task") val updatedTask: TaskResponse? = null  // Updated task after completion (for UI kanban update)
) {
    // Helper for backwards compatibility
    val completionDate: String get() = completedAt
    val completedByName: String? get() = completedBy?.displayName

    // Backwards compatibility for UI that expects these fields
    val task: Int get() = taskId
    val contractor: Int? get() = null  // Not in Go API - would need to be fetched separately
    val contractorDetails: ContractorMinimal? get() = null  // Not in Go API
}

/**
 * Task create request matching Go API CreateTaskRequest
 */
@Serializable
data class TaskCreateRequest(
    @SerialName("residence_id") val residenceId: Int,
    val title: String,
    val description: String? = null,
    @SerialName("category_id") val categoryId: Int? = null,
    @SerialName("priority_id") val priorityId: Int? = null,
    @SerialName("in_progress") val inProgress: Boolean = false,
    @SerialName("frequency_id") val frequencyId: Int? = null,
    @SerialName("custom_interval_days") val customIntervalDays: Int? = null, // For "Custom" frequency
    @SerialName("assigned_to_id") val assignedToId: Int? = null,
    @SerialName("due_date") val dueDate: String? = null,
    @SerialName("estimated_cost") val estimatedCost: Double? = null,
    @SerialName("contractor_id") val contractorId: Int? = null,
    // Set when the task is spawned from a TaskTemplate (onboarding
    // suggestion or browse catalog). Null for free-form custom tasks.
    @SerialName("template_id") val templateId: Int? = null
)

/**
 * Bulk create request matching Go API BulkCreateTasksRequest.
 * Used by onboarding to insert 1-50 tasks atomically in a single
 * transaction. The server forces every entry's residence_id to the
 * top-level value, so any mismatch in the list is silently corrected.
 */
@Serializable
data class BulkCreateTasksRequest(
    @SerialName("residence_id") val residenceId: Int,
    val tasks: List<TaskCreateRequest>
)

/**
 * Bulk create response matching Go API BulkCreateTasksResponse.
 * All [tasks] are created-or-none — partial state never reaches the client.
 */
@Serializable
data class BulkCreateTasksResponse(
    val tasks: List<TaskResponse>,
    val summary: TotalSummary,
    @SerialName("created_count") val createdCount: Int
)

/**
 * Task update request matching Go API UpdateTaskRequest
 * All fields are optional - only provided fields will be updated.
 */
@Serializable
data class TaskUpdateRequest(
    val title: String? = null,
    val description: String? = null,
    @SerialName("category_id") val categoryId: Int? = null,
    @SerialName("priority_id") val priorityId: Int? = null,
    @SerialName("in_progress") val inProgress: Boolean? = null,
    @SerialName("frequency_id") val frequencyId: Int? = null,
    @SerialName("custom_interval_days") val customIntervalDays: Int? = null, // For "Custom" frequency
    @SerialName("assigned_to_id") val assignedToId: Int? = null,
    @SerialName("due_date") val dueDate: String? = null,
    @SerialName("estimated_cost") val estimatedCost: Double? = null,
    @SerialName("actual_cost") val actualCost: Double? = null,
    @SerialName("contractor_id") val contractorId: Int? = null
)

/**
 * Task action response (for cancel, archive, mark in progress, etc.)
 */
@Serializable
data class TaskActionResponse(
    val message: String,
    val task: TaskResponse
)

/**
 * Kanban column response matching Go API KanbanColumnResponse
 */
@Serializable
data class TaskColumn(
    val name: String,
    @SerialName("display_name") val displayName: String,
    @SerialName("button_types") val buttonTypes: List<String>,
    val icons: Map<String, String>,
    val color: String,
    val tasks: List<TaskResponse>,
    val count: Int
)

/**
 * Kanban board response matching Go API KanbanBoardResponse
 * NOTE: Summary statistics are calculated client-side from kanban data
 */
@Serializable
data class TaskColumnsResponse(
    val columns: List<TaskColumn>,
    @SerialName("days_threshold") val daysThreshold: Int,
    @SerialName("residence_id") val residenceId: String
)

/**
 * Task patch request for partial updates (status changes, archive/unarchive)
 */
@Serializable
data class TaskPatchRequest(
    @SerialName("in_progress") val inProgress: Boolean? = null,
    @SerialName("is_archived") val archived: Boolean? = null,
    @SerialName("is_cancelled") val cancelled: Boolean? = null
)

/**
 * Task completion image model
 */
@Serializable
data class TaskCompletionImage(
    val id: Int,
    @SerialName("image_url") val imageUrl: String,
    @SerialName("media_url") val mediaUrl: String? = null, // Authenticated endpoint: /api/media/completion-image/{id}
    val caption: String? = null,
    @SerialName("uploaded_at") val uploadedAt: String? = null
) {
    // Alias for backwards compatibility
    val image: String get() = imageUrl
}

// Type aliases for backwards compatibility with existing code
typealias CustomTask = TaskResponse
typealias TaskDetail = TaskResponse
typealias TaskCompletion = TaskCompletionResponse
