package com.example.myapplication.api.item

import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.pdf.PdfDocument
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import com.example.myapplication.api.MyServerService
import com.example.myapplication.api.report.ReportRemote
import com.example.myapplication.database.entities.model.Item
import com.example.myapplication.database.entities.repository.OfflineRentItemRepository
import com.example.myapplication.database.entities.repository.OfflineItemRepository
import com.example.myapplication.database.entities.repository.OfflineUserItemRepository
import com.example.myapplication.database.entities.repository.ItemRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.IOException
import java.io.OutputStream

class RestItemRepository(
    private val service: MyServerService,
    private val dbItemRepository: OfflineItemRepository,
    private val dbUserItemRepository: OfflineUserItemRepository,
    private val dbRentItemRepository: OfflineRentItemRepository,
) : ItemRepository {
    override suspend fun getItem(uid: Int): Item {
        return service.getItem(uid).toItem()
    }

    override suspend fun insertItem(item: Item) {
        dbItemRepository.insertItem(
            service.createItem(item.toItemRemote()).toItem()
        )
    }

    override suspend fun updateItem(item: Item) {
        dbItemRepository.updateItem(
            service.updateItem(
                item.uid,
                item.toItemRemote()
            ).toItem()
        )
    }

    override suspend fun deleteItem(item: Item) {
        val cart = service.getUsers()
        cart.forEach { userRemote ->
            userRemote.items = userRemote.items.filter { x -> x.id != item.uid }
            userRemote.id?.let { service.updateUserCart(it, userRemote) }
        }
        val rents = service.getRents()
        rents.forEach { rentRemote ->
            rentRemote.items = rentRemote.items.filter { x -> x.id != item.uid }
            service.updateRent(rentRemote.id, rentRemote)
        }
        service.deleteItem(item.uid)
        dbUserItemRepository.deleteItemsByUid(item.uid)
        dbRentItemRepository.deleteItemsByUid(item.uid)
        dbItemRepository.deleteItem(item)
    }
    suspend fun getReport(fromDate: String, toDate: String):List<ReportRemote>
    {
        return service.getReportInfo(fromDate,toDate)
    }


    suspend fun createPdfFile(context: Context, fileName: String, reportData: List<ReportRemote>) {
        withContext(Dispatchers.IO) {
            val contentValues = ContentValues().apply {
                put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
                put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf")
                put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS)
            }

            val contentResolver: ContentResolver = context.contentResolver
            val uri: Uri? = contentResolver.insert(MediaStore.Files.getContentUri("external"), contentValues)

            uri?.let {
                try {
                    contentResolver.openOutputStream(uri)?.use { outputStream ->
                        createPdfContent(outputStream, reportData)
                    }

                    // Optional: Notify MediaStore about the new file
                    context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri))
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
        }
    }

    private fun createPdfContent(outputStream: OutputStream, reportData: List<ReportRemote>) {
        val pdfDocument = PdfDocument()

        val pageInfo = PdfDocument.PageInfo.Builder(595, 842, 1).create()
        val page = pdfDocument.startPage(pageInfo)
        val canvas = page.canvas

        val paint = Paint()
        paint.textSize = 16f // Уменьшаем размер шрифта для лучшей видимости
        paint.isAntiAlias = true

        // Отображаем заголовок
        val title = "Отчет"
        val xTitle = (pageInfo.pageWidth - paint.measureText(title)) / 2
        val yTitle = 40f
        canvas.drawText(title, xTitle, yTitle, paint)

        // Отображаем данные в виде таблицы
        val tableStartY = yTitle + 80f
        val columnWidths = floatArrayOf(0.5f, 1.5f, 1f, 1.5f, 1f) // Увеличиваем ширину столбцов
        val rowHeight = 30f // Увеличиваем высоту строки

        drawTableRow(canvas, arrayOf("ID", "Дата проверки", "Вес", "Количество", "ID велосипеда"), columnWidths, tableStartY, paint)

        for ((index, report) in reportData.withIndex()) {
            val row = arrayOf(
                report.id.toString(),
                report.dateTime.toString(),
                report.weight.toString(),
                report.maxCount.toString(),
                report.bikeId.toString()
            )
            drawTableRow(canvas, row, columnWidths, tableStartY + (index + 1) * rowHeight, paint)
        }

        pdfDocument.finishPage(page)

        pdfDocument.writeTo(outputStream)
        pdfDocument.close()
    }

    private fun drawTableRow(
        canvas: Canvas,
        row: Array<String>,
        columnWidths: FloatArray,
        y: Float,
        paint: Paint
    ) {
        var x = 40f
        for (i in row.indices) {
            val text = row[i]
            canvas.drawText(text, x, y, paint)
            x += columnWidths[i] * 80 // Увеличиваем ширину столбцов
        }
    }
}