package com.fieldlabel.collector.ui.viewmodel

import android.content.Context
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.fieldlabel.collector.data.CollectionRepository
import com.fieldlabel.collector.domain.model.CollectionRecord
import com.fieldlabel.collector.domain.model.SpecimenPhoto
import com.fieldlabel.collector.service.ExportService
import com.fieldlabel.collector.service.ExportState
import com.fieldlabel.collector.service.PrintResult
import com.fieldlabel.collector.service.PrinterService
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.io.File
import javax.inject.Inject

/** 一括印刷状態 */
sealed class BatchPrintState {
    object Idle      : BatchPrintState()
    object Printing  : BatchPrintState()
    data class Done (val message: String) : BatchPrintState()
    data class Error(val message: String) : BatchPrintState()
}

@HiltViewModel
class LocationDetailViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    @ApplicationContext private val context: Context,
    private val repository: CollectionRepository,
    private val exportService: ExportService,
    private val printerService: PrinterService
) : ViewModel() {

    val locationId: String = checkNotNull(savedStateHandle["locationId"])

    // ── 標本一覧（リアルタイム） ──────────────────────────────────────────────
    val specimens: StateFlow<List<CollectionRecord>> = repository.allRecords
        .map { all -> all.filter { it.locationId == locationId } }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), emptyList())

    // ── 写真一覧（リアルタイム） ──────────────────────────────────────────────
    val photos: StateFlow<List<SpecimenPhoto>> =
        repository.getPhotosForLocationFlow(locationId)
            .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), emptyList())

    // ── エクスポート状態 ──────────────────────────────────────────────────────
    private val _exportState = MutableStateFlow<ExportState>(ExportState.Idle)
    val exportState: StateFlow<ExportState> = _exportState.asStateFlow()

    // ── 標本 CRUD ─────────────────────────────────────────────────────────────

    fun deleteRecord(record: CollectionRecord) {
        viewModelScope.launch { repository.deleteRecord(record) }
    }

    fun updateRecord(record: CollectionRecord) {
        viewModelScope.launch { repository.updateRecord(record) }
    }

    // ── 写真操作 ──────────────────────────────────────────────────────────────

    fun deletePhoto(photo: SpecimenPhoto) {
        viewModelScope.launch {
            repository.deletePhoto(photo)
            File(photo.filePath).delete()
        }
    }

    // ── エクスポート ──────────────────────────────────────────────────────────

    /**
     * この地点の標本・写真をエクスポートする。
     * @param includePhotos true → XLSX + 写真を ZIP にまとめる
     *                      false → XLSX のみ
     */
    fun exportLocation(includePhotos: Boolean) {
        if (_exportState.value is ExportState.InProgress) return
        viewModelScope.launch(Dispatchers.IO) {
            _exportState.value = ExportState.InProgress
            try {
                val recs        = specimens.value
                val media       = photos.value
                val fieldDefs   = repository.allCustomFieldDefs.first()
                val fieldValues = repository.getCustomFieldValuesForLocation(locationId)
                val file = if (includePhotos) {
                    exportService.buildZip(recs, media, fieldDefs, fieldValues)
                } else {
                    exportService.buildXlsx(recs, emptyList(), fieldDefs, fieldValues)
                }
                _exportState.value = ExportState.Done(file)
            } catch (e: Throwable) {
                android.util.Log.e(
                    "LocationDetailViewModel",
                    "exportLocation failed: ${e.javaClass.simpleName}: ${e.message}", e
                )
                _exportState.value = ExportState.Error(e.message ?: "エクスポートに失敗しました")
            }
        }
    }

    fun clearExportState() {
        _exportState.value = ExportState.Idle
    }

    // ── 標本一括印刷 ──────────────────────────────────────────────────────────

    private val _batchPrintState = MutableStateFlow<BatchPrintState>(BatchPrintState.Idle)
    val batchPrintState: StateFlow<BatchPrintState> = _batchPrintState.asStateFlow()

    /**
     * この地点の全標本ラベルを 1 回のジョブで連続印刷する。
     * ラベルは水平方向に連結されて 1 枚のテープとして排出される。
     */
    fun printAllSpecimens() {
        if (_batchPrintState.value is BatchPrintState.Printing) return
        viewModelScope.launch {
            _batchPrintState.value = BatchPrintState.Printing
            try {
                val recs = specimens.value
                if (recs.isEmpty()) {
                    _batchPrintState.value = BatchPrintState.Error("印刷対象の標本がありません")
                    return@launch
                }
                val widthMm = repository.tapeWidthMm.first()
                val result  = printerService.printLabelsAsBatch(recs, widthMm)
                _batchPrintState.value = when (result) {
                    is PrintResult.Success -> BatchPrintState.Done(
                        "標本ラベル ${recs.size}枚 連続印刷完了"
                    )
                    is PrintResult.Error   -> BatchPrintState.Error(result.message)
                }
            } catch (e: Throwable) {
                android.util.Log.e(
                    "LocationDetailViewModel",
                    "printAllSpecimens failed: ${e.javaClass.simpleName}: ${e.message}", e
                )
                _batchPrintState.value = BatchPrintState.Error(e.message ?: "印刷エラー")
            }
        }
    }

    fun clearBatchPrintState() {
        _batchPrintState.value = BatchPrintState.Idle
    }
}
