Imports System.Reflection
Imports System.Runtime.Remoting.Metadata.W3cXsd2001
Imports System.Text
Imports MySql.Data.MySqlClient

Public Class mainform
    Private Sub mainform_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Text = "DUALSONIC Authentication Register Program Ver 1.1.6"
        lowProdListLoad()
    End Sub

    Private PackOk As Boolean = False
    Private StateOk As Boolean = False

    Private Const COL_COUNT As Byte = 19

    Private lowProdflag As Boolean = False ''언제 초기화 해줄지 결정해야함

    Private lowProd88List As New Dictionary(Of String, String) ''key : 88코드 value: 모델코드&컬러


    Private Sub BtnOrderSearch_Click(sender As Object, e As EventArgs) Handles btnOrderSearch.Click
        lbWait.Visible = True
        lbWait.Refresh()
        dgvNormal.Rows.Clear()
        mcDate.Enabled = False

        Dim genuineProductDtos = GetGenuineDatasByDate(mcDate.SelectionStart)

        If genuineProductDtos.Count > 0 Then
            For Each genuineProductDto As GenuineProductDto In genuineProductDtos
                Dim RowData(COL_COUNT) As String

                RowData(0) = genuineProductDto.Seq
                RowData(1) = genuineProductDto.ModelCode
                RowData(2) = genuineProductDto.Model
                RowData(3) = genuineProductDto.InvoiceNumber
                RowData(4) = genuineProductDto.PackingSn
                RowData(5) = genuineProductDto.BodySn
                RowData(6) = genuineProductDto.FaceSn
                RowData(7) = genuineProductDto.EyeSn
                RowData(8) = genuineProductDto.BuyRental
                RowData(9) = genuineProductDto.CountryCode
                RowData(10) = genuineProductDto.ManufactureDate
                RowData(11) = genuineProductDto.BuyDate
                RowData(12) = genuineProductDto.SalesStore
                RowData(13) = genuineProductDto.SalesOrderNo
                RowData(14) = genuineProductDto.OrderName
                RowData(15) = genuineProductDto.RecipientName
                RowData(16) = genuineProductDto.OrderHp
                RowData(17) = genuineProductDto.OrderAddress
                RowData(18) = genuineProductDto.Note

                dgvNormal.Rows.Add(RowData)
            Next
            MsgBox("총 건수: " & genuineProductDtos.Count)
        Else
            MsgBox("진행한 일반 포장건이 존재하지 않습니다.", vbExclamation)

            If PackOk = False And StateOk = False Then
                mcDate.Enabled = True
            End If
        End If
        lowProdflag = False
        lbWait.Visible = False
        lbWait.Refresh()
    End Sub
    Private Sub lowProdListLoad()
        lowProdList(lowProd88List)
    End Sub
    Private Function GetGenuineDatasByDate(targetDate As Date) As List(Of GenuineProductDto)
        Dim results = FindSerialsByDate(targetDate)

        Dim individualSerials = results.Item1
        Dim bundledSerials = results.Item2

        Dim genuineProductDtoMap As New Dictionary(Of String, GenuineProductDto)

        For Each serial In individualSerials
            If lowProd88List.Count <> 0 Then
                If lowProd88List.ContainsKey(serial) Then

                    If lowProdflag = False Then
                        For Each dt In getOyList(lowProd88List)
                            genuineProductDtoMap.Add(dt.Key, dt.Value)
                        Next
                        lowProdflag = True
                    End If

                    Continue For
                End If
            End If
            Dim genuineProductDto As New GenuineProductDto(serial)
            genuineProductDtoMap(serial) = genuineProductDto
        Next

        FillGenuineProductDto(individualSerials, bundledSerials, genuineProductDtoMap)

        Return genuineProductDtoMap.Values.ToList()
    End Function

    Private Sub FillGenuineProductDto(individualSerials As List(Of String), bundledSerials As List(Of String), dtoMap As Dictionary(Of String, GenuineProductDto))
        Dim inClauses = BuildInClauses(individualSerials, maxPerQuery:=100)
        Dim likeClauses = BuildLikeClauses(bundledSerials, maxPerClause:=100, field:="Serial_Number")

        FillFromOrderTblByLike(dtoMap, likeClauses)
        FillFromOrderTblByIn(dtoMap, inClauses)
        FillFromProductTbl(dtoMap, inClauses)
        FillFromProdData(dtoMap, inClauses)
    End Sub

    Private Function BuildInClauses(serials As IEnumerable(Of String), maxPerQuery As Integer) As List(Of String)
        Dim inClauseList As New List(Of String)()
        Dim temp As New List(Of String)()

        For Each sn In serials.Distinct()
            temp.Add("'" & sn.Replace("'", "''") & "'")
            If temp.Count >= maxPerQuery Then
                inClauseList.Add("(" & String.Join(",", temp) & ")")
                temp.Clear()
            End If
        Next

        If temp.Count > 0 Then
            inClauseList.Add("(" & String.Join(",", temp) & ")")
        End If

        Return inClauseList
    End Function

    Private Function BuildLikeClauses(serials As List(Of String), maxPerClause As Integer, field As String) As List(Of String)
        Dim likeClauses As New List(Of String)()
        Dim temp As New List(Of String)()

        For Each sn In serials.Distinct()
            If Not String.IsNullOrWhiteSpace(sn) Then
                Dim cleanedSn = sn.Trim().Replace("'", "''")
                temp.Add(field & " LIKE '%" & cleanedSn & "%'")
            End If

            If temp.Count >= maxPerClause Then
                likeClauses.Add(String.Join(" OR ", temp))
                temp.Clear()
            End If
        Next

        If temp.Count > 0 Then
            likeClauses.Add(String.Join(" OR ", temp))
        End If

        Return likeClauses
    End Function

    Private Sub BtnCsv_Click(sender As Object, e As EventArgs) Handles btnCsv.Click
        Try
            lbsave.Text = "변환중.."
            lbsave.Visible = True
            lbsave.Refresh()

            If dgvNormal.Rows.Count = 1 Then
                MsgBox("먼저 데이터를 불러와 주십시오.", vbExclamation)
            Else
                ' 파일 경로 설정
                Dim FilePath As String = System.AppDomain.CurrentDomain.BaseDirectory & "\AuthData"
                If Dir(FilePath, vbDirectory) = "" Then
                    MkDir(FilePath)
                End If

                ' 파일 이름 설정
                Dim FileName As String = FilePath & "\Auth_N_" & mcDate.SelectionStart & ".csv"
                Dim WriteData As String = String.Empty

                ' CSV의 헤더
                Dim StartData As String = "seq,model_code,model,invoice_number,packing_sn,body_sn,face_sn,eye_sn,buy_rental,country_code,manufacture_date,buy_date,sales_store,sales_order_no,order_name,recipient_name,order_hp,order_address,note"
                WriteData = StartData & vbCrLf

                ' 데이터를 추가
                For i = 0 To dgvNormal.Rows.Count - 2
                    ' 각 셀의 값을 따옴표로 감싸고, 콤마를 포함하는지 확인
                    Dim SaveData As String = String.Join(",", dgvNormal.Rows(i).Cells.Cast(Of DataGridViewCell).Select(Function(cell) EncloseInQuotesIfNeeded(cell.Value.ToString)))

                    ' 데이터를 줄바꿈하면서 추가
                    WriteData &= SaveData & vbCrLf
                Next

                ' 파일에 쓰기
                System.IO.File.WriteAllText(FileName, WriteData, System.Text.Encoding.UTF8)

                MsgBox("변환 완료!", vbInformation)
            End If

        Catch ex As Exception
            MsgBox(".csv 로 변환하는데 오류가 발생하였습니다." & vbCrLf & ex.Message)
        End Try

        lbsave.Visible = False
        lbsave.Refresh()
    End Sub

    ' 콤마가 있는 필드에 대해 이중 따옴표로 감싸는 함수
    Private Function EncloseInQuotesIfNeeded(value As String) As String
        ' 값에 콤마 또는 따옴표가 포함되어 있으면 따옴표로 감싼다
        If value.Contains(",") OrElse value.Contains("""") Then
            ' 따옴표를 이스케이프하기 위해 따옴표 두 개로 변경 (CSV 규칙에 맞게)
            value = value.Replace("""", """""")
            Return $"""{value}"""
        Else
            Return value
        End If
    End Function

    Private Sub BtnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
        lbsave.Text = "저장중.."
        lbsave.Visible = True
        lbsave.Refresh()

        If dgvNormal.Rows.Count = 1 Then
            MsgBox("불러온 데이터가 존재하지 않습니다. 데이터를 먼저 불러와 주십시오.", vbExclamation)
        Else
            Dim UpdateData As String = String.Empty

            For i = 0 To dgvNormal.Rows.Count - 2

                Dim RowData As String = String.Empty

                For n = 1 To dgvNormal.ColumnCount - 1

                    If RowData = String.Empty Then

                        If String.IsNullOrWhiteSpace(dgvNormal.Rows(i).Cells(n).Value.ToString) Then
                            RowData = "NULL"
                        Else
                            dgvNormal.Rows(i).Cells(n).Value = dgvNormal.Rows(i).Cells(n).Value.ToString.Replace("'", "''")
                            RowData = "'" & dgvNormal.Rows(i).Cells(n).Value.ToString & "'"
                        End If

                    Else

                        If String.IsNullOrWhiteSpace(dgvNormal.Rows(i).Cells(n).Value.ToString) Then
                            RowData = RowData & "," & "NULL"
                        Else
                            dgvNormal.Rows(i).Cells(n).Value = dgvNormal.Rows(i).Cells(n).Value.ToString.Replace("'", "''")
                            RowData = RowData & "," & "'" & dgvNormal.Rows(i).Cells(n).Value.ToString & "'"
                        End If

                    End If

                Next

                If UpdateData = String.Empty Then
                    UpdateData = "(" & RowData & ")"
                Else
                    UpdateData = UpdateData & "," & vbCrLf & "(" & RowData & ")"
                End If

            Next

            Const ColName As String = "(model_code,model,invoice_number,packing_sn,body_sn,face_sn,eye_sn,buy_rental,country_code,manufacture_date,buy_date,sales_store,sales_order_no,order_name,recipient_name,order_hp,order_address,note)"

            UpdateData = "INSERT INTO fm_genuine" & ColName & " VALUES " & UpdateData

            If SSHCommand(UpdateData) Then
                If updateOliveYoungGenuineDate(lowProd88List) Then
                    dgvNormal.Rows.Clear()
                    MsgBox("저장 완료 !", vbInformation)
                Else
                    MsgBox("저장 실패 !", vbCritical)
                End If
            Else
            MsgBox("저장 실패 !", vbCritical)
        End If
        End If

        lbsave.Visible = False
        lbsave.Refresh()
    End Sub

    Private Sub BtnLoad_Click(sender As Object, e As EventArgs) Handles btnLoad.Click
        lbWait.Visible = True
        lbWait.Refresh()

        dgvNormal.Rows.Clear()

        Dim DBCmd As String = "SELECT seq,model_code,model,invoice_number,packing_sn,body_sn,face_sn,eye_sn,buy_rental,country_code,manufacture_date,buy_date,sales_store,sales_order_no,order_name,recipient_name,order_hp,order_address,note FROM fm_genuine WHERE buy_date = '" & mcDate.SelectionStart & "'"

        If SSHQueryReader(DBCmd) Then
            Dim RowNum As Short = (sshDataQuery.Length / COL_COUNT) - 1
            Dim ColNum As Byte = COL_COUNT - 1
            Dim SqlCount As Short = 0

            For i = 0 To RowNum

                Dim RowData(ColNum) As String

                For n = 0 To ColNum
                    RowData(n) = sshDataQuery(SqlCount)

                    SqlCount += 1
                Next

                dgvNormal.Rows.Add(RowData)

            Next
        Else
            MsgBox("등록된 데이터가 존재하지 않습니다.", vbExclamation)
        End If

        lbWait.Visible = False
        lbWait.Refresh()
    End Sub
    Private Sub BtnReset_Click(sender As Object, e As EventArgs) Handles btnReset.Click
        mcDate.Enabled = True
        dgvNormal.Rows.Clear()
    End Sub
End Class
