package com.webtoonviewer.network

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Log
import com.hierynomus.msdtyp.AccessMask
import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation
import com.hierynomus.mssmb2.SMB2CreateDisposition
import com.hierynomus.mssmb2.SMB2ShareAccess
import com.hierynomus.smbj.SMBClient
import com.hierynomus.smbj.auth.AuthenticationContext
import com.hierynomus.smbj.connection.Connection
import com.hierynomus.smbj.session.Session
import com.hierynomus.smbj.share.DiskShare
import com.hierynomus.smbj.share.File
import com.webtoonviewer.storage.StorageManager
import com.webtoonviewer.utils.CommonUtils.pathJoin
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
import java.io.FileOutputStream
import java.io.InputStream
import java.io.OutputStream

class SmbClientHelper(private val context: Context) {
    private lateinit var connection: Connection
    private lateinit var session: Session
    private lateinit var share: DiskShare

    suspend fun connect(): Boolean {
        return try {
            val client = SMBClient()

            // 使用 withContext 切换到 IO 线程执行连接操作
            withContext(Dispatchers.IO) {
                connection = client.connect(ConnectionData.HOSTNAME)
                Log.d("SmbClientHelper", "Connected to server: ${ConnectionData.HOSTNAME}")

                val ac = AuthenticationContext(
                    ConnectionData.USERNAME, ConnectionData.PASSWORD.toCharArray(),
                    ConnectionData.DOMAIN
                )
                session = connection.authenticate(ac)
                Log.d("SmbClientHelper", "Authenticated with username: ${ConnectionData.USERNAME}")

                share = session.connectShare(ConnectionData.SHARED_FOLDER) as DiskShare
                Log.d("SmbClientHelper", "Connected to share: ${ConnectionData.SHARED_FOLDER}")
                true
            }
        } catch (e: Exception) {
            // 捕获 SMB 连接异常
            Log.e("SmbClientHelper", "Error connecting to share", e)
            false
        }
    }

    fun getTitlesFromShare(): List<FileIdBothDirectoryInformation> {
        return share.list(ConnectionData.WEBTOON_FOLDER)
    }

    fun getEpisodesFormShare(title: String): List<FileIdBothDirectoryInformation> {
        val path = ConnectionData.WEBTOON_FOLDER + "/"  + title
        return share.list(path)
    }

    fun getChapterSumFromShare(title: String): Int {
        val path = ConnectionData.WEBTOON_FOLDER + "/" + title
        return share.list(path).count() - 3
    }

    fun getInformationFile(title: String): File {
        return share.openFile(
            pathJoin(ConnectionData.WEBTOON_FOLDER, title, "information.json"),
            setOf(AccessMask.GENERIC_READ),
            null,
            SMB2ShareAccess.ALL,
            SMB2CreateDisposition.FILE_OPEN,
            null
        )
    }

    suspend fun getImagePathsFromShare(title: String, episode: String): MutableList<String> {
        val episodeFolderPath = pathJoin(ConnectionData.WEBTOON_FOLDER, title, episode)
        return withContext(Dispatchers.IO) {
            var imageNames = mutableListOf<String>()
            for (item in share.list(episodeFolderPath)) {
                val fileInfo = item as FileIdBothDirectoryInformation
                if (fileInfo.fileName.endsWith(".jpg", true)) {
                    imageNames.add(fileInfo.fileName)
                }
            }
            imageNames = imageNames.sortedBy { it.substringBefore('.').toInt() }.toMutableList()
            imageNames.map { "$episodeFolderPath/$it" }.toMutableList()
        }
    }

    suspend fun loadImageFromShare(imagePath: String): Bitmap? {
        return withContext(Dispatchers.IO) {
            val file = share.openFile(
                imagePath,
                setOf(AccessMask.GENERIC_READ),
                null,
                SMB2ShareAccess.ALL,
                SMB2CreateDisposition.FILE_OPEN,
                null
            )

            val outputStream = ByteArrayOutputStream()
            val inputStream: InputStream = file.inputStream
            inputStream.copyTo(outputStream)
            file.close()

            val imageData = outputStream.toByteArray()
            BitmapFactory.decodeByteArray(imageData, 0, imageData.size)
        }
    }

    suspend fun downloadWebtoon(title: String) {
        withContext(Dispatchers.IO) {
            for (episode in getEpisodesFormShare(title)) {
                if (episode.fileName != "." && episode.fileName != ".." && !episode.fileName.contains("information")) {
                    val dirName = title + "/" + episode.fileName
                    if (!StorageManager.isDirectoryExists(context, dirName)) {
                        StorageManager.createDirectory(context, dirName)
                        copyImages(getImagePathsFromShare(title, episode.fileName))
                    }
                }
            }
        }
    }

    private suspend fun copyImages(imagePaths: MutableList<String>) {
        withContext(Dispatchers.IO) {
            for (imagePath in imagePaths) {
                val file = share.openFile(
                    imagePath,
                    setOf(AccessMask.GENERIC_READ),
                    null,
                    SMB2ShareAccess.ALL,
                    SMB2CreateDisposition.FILE_OPEN,
                    null
                )

                val outputFile = StorageManager.generateOutputFile(context, imagePath)
                Log.d("ithi", "copyImages: ${outputFile}")
                FileOutputStream(outputFile).use { outputStream ->
                    file.inputStream.use { inputStream ->
                        copyStream(inputStream, outputStream)
                    }
                }
                Log.d("SmbClientHelper", "Saved image to: ${outputFile.absolutePath}")
            }
        }
    }

//    private suspend fun copyImages(imagePaths: MutableList<String>) {
//        withContext(Dispatchers.IO) {
//            for (imagePath in imagePaths) {
//                val file = share.openFile(
//                    imagePath,
//                    setOf(AccessMask.GENERIC_READ),
//                    null,
//                    SMB2ShareAccess.ALL,
//                    SMB2CreateDisposition.FILE_OPEN,
//                    null
//                )
//                val outputFile = externalStorageHelper.generateOutputFile(imagePath)
//                if (outputFile != null) {
//                    FileOutputStream(outputFile).use { outputStream ->
//                        file.inputStream.use { inputStream ->
//                            copyStream(inputStream, outputStream)
//                        }
//                    }
//                    Log.d("SmbClientHelper", "Saved image to: ${outputFile.absolutePath}")
//                }
//            }
//        }
//    }

    private fun copyStream(inputStream: InputStream, outputStream: OutputStream) {
        val buffer = ByteArray(1024 * 4) // 4KB buffer
        var bytesRead: Int
        while (inputStream.read(buffer).also { bytesRead = it } != -1) {
            outputStream.write(buffer, 0, bytesRead)
        }
        outputStream.flush()
    }

    suspend fun disconnect() {
        try {
            withContext(Dispatchers.IO) {
                share.close()
                session.close()
                connection.close()
            }
        } catch (e: Exception) {
            Log.e("SmbClientHelper", "Error disconnecting", e)
        }
    }
}