Imports System.Data
Imports System.IO
Imports AppCommon
Imports AppVariable
Imports System.Net
Imports System.Web

Partial Class training_applyconfirm
    Inherits System.Web.UI.Page

#Region "******************** メンバ変数 ********************"
    Private _search As TrainingSearch
    Private _param As TrainingParam
    Private _user As LoginUser
    Private trainingTel As String = Com_Get_変数("PT_COMMON_TRAINING_TEL")
    Private DBServerAuthUserId As String = ConfigurationManager.AppSettings("WebDavAuthUserId").ToString()
    Private DBServerAuthUserPass As String = ConfigurationManager.AppSettings("WebDavAuthUserPass").ToString()

#End Region

#Region "******************** ページイベント ********************"
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        _search = DirectCast(Session(S_Training_Search), TrainingSearch)
        _param = DirectCast(Session(S_Training_Seleted_Param), TrainingParam)
        _user = DirectCast(Session(S_COM_LoginUser), LoginUser)

        'JavaScript の alert で表示する処理完了メッセージ
        If Not String.IsNullOrEmpty(Session(S_Training_ClientMessage)) Then
            Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "myalert", "<script language=JavaScript>alert('" & Session(S_Training_ClientMessage) & "');</script>", False)
            Session(S_Training_ClientMessage) = String.Empty
        End If

        If Not IsPostBack() Then
            uc_TrainingInfo.Create研修詳細()
            Create申込状況()
            AdjustButtons()
            Bind申込()
        End If
    End Sub
#End Region

#Region "***************** コントロールイベント *****************"
    Protected Sub btn_研修一覧_Click(ByVal sender As Object, ByVal e As EventArgs)
        _search.ForceSearch = True
        Session(S_Training_Search) = _search

        'ページ遷移
        Response.Redirect(Com_Get_Content(FunctionCd.TrainingList))
    End Sub

    Protected Sub btn_追加申込_Click(ByVal sender As Object, ByVal e As EventArgs)
        _param.Mode = ScreenMode.Additions
        _param.Referer = FunctionCd.TrainingApplyConfirm
        Session(S_Training_Seleted_Param) = _param

        'ページ遷移
        Response.Redirect(Com_Get_Content(FunctionCd.TrainingApplyRegister))
    End Sub

    Protected Sub btn_編集_Click(ByVal sender As Object, ByVal e As EventArgs)
        _param.Mode = ScreenMode.Edits
        _param.Referer = FunctionCd.TrainingApplyConfirm
        Session(S_Training_Seleted_Param) = _param

        'ページ遷移
        Response.Redirect(Com_Get_Content(FunctionCd.TrainingApplyRegister))
    End Sub

    Protected Sub btn_申込取消_Click(ByVal sender As Object, ByVal e As EventArgs)

        If Cancel申込() Then

            Dim applyNo As String = lb_学籍NO.Text
            Dim userCd As String = Session(S_COM_UserCD).ToString()

            If Not String.IsNullOrEmpty(applyNo) Then

                Dim sucFlg = AppMail.SendApplyCancelMail(userCd, applyNo)

                If sucFlg Then
                    Dim msg As String = ""
                    msg &= "申込取消を受け付けました。"
                    msg &= "\r\n" & "後ほど取消完了のメールが届きます。"
                    msg &= "\r\n" & "完了メールが届かない場合は、研修部あてに電話"
                    msg &= "\r\n" & "をしてください。(TEL："
                    msg &= trainingTel
                    msg &= ")"

                    Session(S_Training_ClientMessage) = msg

                    _search.ForceSearch = True
                    Session(S_Training_Search) = _search

                    'ページ遷移
                    Response.Redirect(Com_Get_Content(FunctionCd.TrainingList))
                End If
            End If

        Else
            Dim msg As String = ""
            msg &= "申込取消に失敗しました"
            msg &= "\r\n" & "管理者にお問い合わせください。"
            Session(S_Training_ClientMessage) = msg

            _search.ForceSearch = True
            Session(S_Training_Search) = _search

        End If

    End Sub

    Protected Sub btn_書類提出_Click(ByVal sender As Object, ByVal e As EventArgs)
        _param.Referer = FunctionCd.TrainingApplyConfirm

        Dim fncCd As String
        Select Case DirectCast(frm_申込状況.FindControl("lb_申告書提出"), Label).Text
            Case "済み"
                fncCd = FunctionCd.TrainingDocumentConfirm
                _param.Mode = ScreenMode.Edits
            Case "一時保存"
                fncCd = FunctionCd.TrainingDocumentRegister
                _param.Mode = ScreenMode.Temporary
            Case Else
                fncCd = FunctionCd.TrainingDocumentRegister
                _param.Mode = ScreenMode.Additions
        End Select

        Session(S_Training_Seleted_Param) = _param


        'ページ遷移
        Response.Redirect(Com_Get_Content(fncCd))
    End Sub

    Protected Sub btn_決定通知_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btn_決定通知.Click
        Dim docName As String = "決定通知兼請求書"
        Dim lb_受講状況 As Label = CType(frm_申込状況.FindControl("lb_受講状況"), Label)

        '受講不可のときは不可通知書をDL
        If lb_受講状況.Text = "受講不可" Then
            docName = "不可通知"
        End If

        Dim folderPath As String = Com_Get_変数("PT_KETTEI_DIRECTORY")
        DownLoadDocument(folderPath, docName, "")
    End Sub

    Protected Sub btn_修了証書_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btn_修了証書.Click
        Dim docName As String = "修了証書"
        Dim folderPath As String = Com_Get_変数("PT_SHURYO_DIRECTORY")

        '修了証書、受講証明書はファイル名に席番も出力　2025/03/07 S.Iguchi Add
        Dim lb_席番 As Label = CType(frm_申込状況.FindControl("lb_席番"), Label)
        Dim sekiNo As String = lb_席番.Text

        DownLoadDocument(folderPath, docName, sekiNo)
    End Sub

    Protected Sub btn_受講証明書_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btn_受講証明書.Click
        Dim docName As String = "受講証明書"
        Dim folderPath As String = Com_Get_変数("PT_JUKOU_DIRECTORY")
        '修了証書、受講証明書はファイル名に席番も出力　2025/03/07 S.Iguchi Add
        Dim lb_席番 As Label = CType(frm_申込状況.FindControl("lb_席番"), Label)
        Dim sekiNo As String = lb_席番.Text

        DownLoadDocument(folderPath, docName, sekiNo)
    End Sub

#End Region

#Region "******************* Sub及びFunction ********************"
    Private Sub Create申込状況()
        Using spm As New StoredProcedureManager("申込_研修申込_SELECT")
            spm.AddPrmIn("@履修年度", SqlDbType.SmallInt, _param.履修年度)
            spm.AddPrmIn("@成績年度", SqlDbType.SmallInt, _param.成績年度)
            spm.AddPrmIn("@分野CD", SqlDbType.VarChar, _param.分野CD)
            spm.AddPrmIn("@科目CD", SqlDbType.VarChar, _param.科目CD)
            spm.AddPrmIn("@講座CD", SqlDbType.VarChar, _param.講座CD)
            spm.AddPrmIn("@連番", SqlDbType.VarChar, _param.連番)
            spm.Fill()

            frm_申込状況.DataSource = spm.ds.Tables(0)
        End Using

        frm_申込状況.DataBind()
    End Sub

    Private Sub Bind申込()
        Dim dt As DataTable
        Using spm As New StoredProcedureManager("申込_研修申込_SELECT")
            spm.AddPrmIn("@履修年度", SqlDbType.SmallInt, _param.履修年度)
            spm.AddPrmIn("@成績年度", SqlDbType.SmallInt, _param.成績年度)
            spm.AddPrmIn("@分野CD", SqlDbType.VarChar, _param.分野CD)
            spm.AddPrmIn("@科目CD", SqlDbType.VarChar, _param.科目CD)
            spm.AddPrmIn("@講座CD", SqlDbType.VarChar, _param.講座CD)
            spm.AddPrmIn("@連番", SqlDbType.Int, _param.連番)
            spm.Fill()

            dt = spm.ds.Tables(0)
        End Using

        lb_学籍NO.Text = dt.Rows(0)("学籍NO").ToString()

        If "True".Equals(dt.Rows(0)("未定").ToString()) Then
            lb_氏名.Text = "(未定)"
            lb_ふりがな.Text = "(未定)"
        Else
            lb_氏名.Text = dt.Rows(0)("氏名").ToString()
            lb_ふりがな.Text = dt.Rows(0)("ふりがな").ToString()
        End If

        Dim str年齢 As String = dt.Rows(0)("年齢").ToString()
        If Not String.IsNullOrEmpty(str年齢) Then
            lb_年齢.Text = str年齢 & "歳"
        End If
        lb_性別.Text = dt.Rows(0)("性別").ToString()
        lb_所属部課.Text = dt.Rows(0)("所属部課").ToString()
        lb_職名.Text = dt.Rows(0)("職名").ToString()
        'lb_補職名.Text = dt.Rows(0)("補職名").ToString
        lb_選任区分.Text = dt.Rows(0)("選任区分").ToString()
        lb_職層.Text = dt.Rows(0)("職層").ToString()
        lb_職種.Text = dt.Rows(0)("職種").ToString()
        Dim str通算経験年数 As String = dt.Rows(0)("通算経験年数").ToString()
        If Not String.IsNullOrEmpty(str通算経験年数) Then
            lb_通算経験年数.Text = str通算経験年数 & "年"
        End If
        Dim str通算経験月数 As String = dt.Rows(0)("通算経験月数").ToString()
        If Not String.IsNullOrEmpty(str通算経験月数) Then
            lb_通算経験月数.Text = str通算経験月数 & "カ月"
        End If
        lb_過去受講不可科目.Text = dt.Rows(0)("過去受講不可科目").ToString()
        Dim str過去受講不可科目_実施年 As String = dt.Rows(0)("過去受講不可科目_実施年").ToString()
        If Not String.IsNullOrEmpty(str過去受講不可科目_実施年) Then
            lb_過去受講不可科目_実施年.Text = str過去受講不可科目_実施年 & "年"
        End If
        lb_過去受講不可科目.Text = dt.Rows(0)("過去受講不可科目").ToString()
        Dim str過去受講不可科目_実施月 As String = dt.Rows(0)("過去受講不可科目_実施月").ToString()
        If Not String.IsNullOrEmpty(str過去受講不可科目_実施月) Then
            lb_過去受講不可科目_実施月.Text = str過去受講不可科目_実施月 & "月"
        End If
        lb_受講経験有無.Text = dt.Rows(0)("受講経験有無").ToString()
        Dim str過去参加回数 As String = dt.Rows(0)("過去参加回数").ToString()
        If Not String.IsNullOrEmpty(str過去参加回数) Then
            lb_過去参加回数.Text = str過去参加回数 & "回"
        End If

        lb_研修担当所属.Text = dt.Rows(0)("研修担当所属").ToString()
        lb_研修担当氏名.Text = dt.Rows(0)("研修担当氏名").ToString()
        lb_研修担当TEL.Text = dt.Rows(0)("研修担当TEL").ToString()
        lb_研修担当EMAIL.Text = dt.Rows(0)("研修担当EMAIL").ToString()
        lb_備考.Text = dt.Rows(0)("備考").ToString()
        lb_任命権者名.Text = dt.Rows(0)("任命権者名").ToString()
        lb_PASSWORD.Text = dt.Rows(0)("PASSWORD").ToString()
    End Sub

    Private Sub AdjustButtons()
        Dim str研修区分 As String = uc_TrainingInfo.研修区分
        Dim bln申込期限超過 As Boolean = uc_TrainingInfo.申込期限超過
        Dim bln新規申込NG As Boolean = Not String.Empty.Equals(uc_TrainingInfo.新規申込NG)
        Dim str受講状況 As String = DirectCast(frm_申込状況.FindControl("lb_受講状況"), Label).Text
        Dim str在籍区分 As String = DirectCast(frm_申込状況.FindControl("lb_在籍区分"), Label).Text

        ' 比較対象の文字列リストを定義
        Dim notAllowedStatuses As New List(Of String) From {"受講不可", "延期", "受講申請中", "未", "辞退", "退所", "中止"}

        '受講状況ステータスが何かしら更新された場合は、編集・キャンセル不可
        If str受講状況 <> "未" Then
            DisabledButton(btn_編集)
            DisabledButton(btn_申込取消)
        End If

        '受講不可のときは決定通知ボタンは有効
        If str受講状況 = "受講不可" Then
            DisabledButton(btn_書類提出)
            DisabledButton(btn_書類提出2)
        ElseIf notAllowedStatuses.Contains(str受講状況) Then
            DisabledButton(btn_決定通知)
            DisabledButton(btn_書類提出)
            DisabledButton(btn_書類提出2)
        End If

        If Not "一般研修".Equals(str研修区分) OrElse Not "修了".Equals(str在籍区分) Then
            DisabledButton(btn_修了証書)
        End If

        If Not "修了".Equals(str在籍区分) Then
            DisabledButton(btn_受講証明書)
        End If

        If bln申込期限超過 Then
            'DisabledButton(btn_追加申込)
            DisabledButton(btn_編集)
            DisabledButton(btn_申込取消)
        End If

        '20250509 締切定員考慮した新規申込制限
        If bln新規申込NG Then
            DisabledButton(btn_追加申込)
            'DisabledButton(btn_編集)
            'DisabledButton(btn_申込取消)
        End If

        If Not "学生".Equals(_user.PORTAL区分) Then
            div_button_student.Visible = False
        End If

        If Not "職員".Equals(_user.PORTAL区分) Then
            div_button_staff.Visible = False
        End If
    End Sub

    Private Sub DisabledButton(ByRef btn As Button)
        btn.Enabled = False
        btn.CssClass = "training-button training-button-disabled"
    End Sub

    Private Function Cancel申込() As Boolean
        Try
            Using spm As New StoredProcedureManager("申込_研修申込_CANCEL")
                spm.AddPrmIn("@履修年度", SqlDbType.SmallInt, _param.履修年度)
                spm.AddPrmIn("@成績年度", SqlDbType.SmallInt, _param.成績年度)
                spm.AddPrmIn("@分野CD", SqlDbType.VarChar, _param.分野CD)
                spm.AddPrmIn("@科目CD", SqlDbType.VarChar, _param.科目CD)
                spm.AddPrmIn("@講座CD", SqlDbType.VarChar, _param.講座CD)
                spm.AddPrmIn("@連番", SqlDbType.Int, _param.連番)
                spm.AddPrmIn("@USERCD", SqlDbType.VarChar, _user.USERCD)

                spm.Exec()
            End Using
            Return True
        Catch ex As Exception
            Return False
        End Try
    End Function

    Private Sub ShowClientAlert(message As String)
        Dim escapedMessage As String = HttpUtility.JavaScriptStringEncode(message)
        Dim script As String = String.Format("alert('{0}');", escapedMessage)
        ScriptManager.RegisterStartupScript(Me, Me.GetType(), "AlertScript", script, True)
    End Sub

    Private Function IsMatchingFile(filePath As String, docName As String, gakusekiNo As String) As Boolean

        Dim fileName As String = Path.GetFileNameWithoutExtension(filePath)
        Dim parts As String() = fileName.Split("_"c)

        ' 条件チェック:
        ' 1. ファイル名が "_" で少なくとも3つの部分に分割できること
        ' 2. 最初の部分が docName と一致すること（大文字小文字を区別しない）
        ' 3. 最後の部分が gakusekiNo と一致すること（大文字小文字を区別しない）
        Return parts.Length >= 3 AndAlso
               parts(0).IndexOf(docName) > 0 AndAlso
               String.Equals(parts(parts.Length - 1), gakusekiNo, StringComparison.OrdinalIgnoreCase)
    End Function

    Private Function GetMatchingFileUrl(baseUrl As String, docName As String, gakusekiNo As String) As String
        Try
            ' WebClientを使用してディレクトリリスティングを取得
            Using client As New WebClient()
                Dim username As String = DBServerAuthUserId
                Dim password As String = DBServerAuthUserPass
                Dim credentials As String = Convert.ToBase64String(Encoding.ASCII.GetBytes(username & ":" & password))
                client.Headers("Authorization") = "Basic " & credentials

                client.Encoding = Encoding.UTF8
                Dim html As String = client.DownloadString(baseUrl)
                Dim detectedEncoding As Encoding = DetectEncodingFromHtml(html)

                If detectedEncoding IsNot Nothing AndAlso Not detectedEncoding.Equals(Encoding.UTF8) Then
                    client.Encoding = detectedEncoding
                    html = client.DownloadString(baseUrl)
                End If

                Dim linkPattern As String = "<a\s+(?:[^>]*?\s+)?href=""([^""]*)"">.*?</a>"
                Dim matches As MatchCollection = Regex.Matches(html, linkPattern, RegexOptions.IgnoreCase)

                For Each match As Match In matches
                    Dim hrefValue As String = match.Groups(1).Value
                    If String.IsNullOrEmpty(hrefValue) Then
                        Continue For ' 空のhref値はスキップ
                    End If

                    Dim fileName As String = Path.GetFileName(hrefValue)
                    If String.IsNullOrEmpty(fileName) Then
                        Continue For ' ファイル名が空の場合はスキップ
                    End If

                    Dim decodedFileName As String = SafeUrlDecode(fileName, detectedEncoding)

                    If IsMatchingFile(decodedFileName, docName, gakusekiNo) Then
                        ' マッチした場合、完全なURLを返す
                        Return New Uri(New Uri(baseUrl), hrefValue).AbsoluteUri
                    End If
                Next
            End Using
        Catch ex As WebException
            If ex.Response IsNot Nothing Then
                Dim response As HttpWebResponse = DirectCast(ex.Response, HttpWebResponse)
                Console.WriteLine(String.Format("エラーコード: {0}", response.StatusCode))
                Console.WriteLine(String.Format("説明: {0}", response.StatusDescription))

                ' レスポンスボディを読み取る
                Using reader As New StreamReader(response.GetResponseStream())
                    Dim responseBody As String = reader.ReadToEnd()
                    Console.WriteLine(String.Format("レスポンスボディ: {0}", responseBody))
                End Using
            End If
            Console.WriteLine(String.Format("エラーメッセージ: {0}", ex.Message))

        Catch ex As Exception

            Console.WriteLine("Error in GetMatchingFileUrl: " & ex.Message)
        End Try

        Return String.Empty
    End Function


    Private Sub DownLoadDocument(folderPath As String, docName As String, sekiNo As String)

        Dim gakusekiNo As String = lb_学籍NO.Text
        Dim risyuNendo As String = _param.履修年度.ToString()
        Dim kaimei As String = uc_TrainingInfo.回名
        Dim extension As String = ".pdf"
        Dim filePath = folderPath
        Dim fileName = ""
        If sekiNo = "" Then
            fileName = "【" & docName & "】" & risyuNendo & "_" & kaimei & "_" & gakusekiNo & extension
        Else
            '修了証書、受講証明書は席番を出力
            fileName = "【" & docName & "】_" & kaimei & "_" & sekiNo & "_" & gakusekiNo & extension
        End If

        Try
            If folderPath.StartsWith("http://") OrElse folderPath.StartsWith("https://") Then
                ' URLの場合
                folderPath = folderPath.Replace("\", "/")
                filePath = folderPath & fileName
                DownloadFromUrl(filePath)
            Else
                filePath = folderPath & fileName
                DownloadLocalFile(filePath)
            End If

        Catch ex As Exception
            ShowClientAlert(docName & "は、未発行です。")
        End Try
    End Sub

    Private Sub DownloadLocalFile(filePath As String)
        Dim fileName As String = Path.GetFileName(filePath)
        If File.Exists(filePath) Then
            Response.ContentType = "application/octet-stream"
            Response.AppendHeader("Content-Disposition", String.Format("attachment; filename=""{0}""", fileName))
            Response.TransmitFile(filePath)
            Response.End()
        Else
            Response.Write("<script>alert('指定されたファイルが存在しません。');</script>")
        End If
    End Sub
    Private Function DetectEncodingFromHtml(html As String) As Encoding
        Dim charsetPattern As String = "<meta\s+charset=[""']?([^""']+)[""']?"
        Dim match As Match = Regex.Match(html, charsetPattern, RegexOptions.IgnoreCase)
        If match.Success Then
            Try
                Return Encoding.GetEncoding(match.Groups(1).Value)
            Catch ex As ArgumentException
                ' 不明なエンコーディングの場合はnull
                Return Nothing
            End Try
        End If
        Return Nothing
    End Function

    Private Function SafeUrlDecode(encodedString As String, encoding As Encoding) As String
        If String.IsNullOrEmpty(encodedString) Then
            Return String.Empty
        End If

        Try
            If encoding Is Nothing Then
                encoding = Encoding.UTF8
            End If
            Return HttpUtility.UrlDecode(encodedString, encoding)
        Catch ex As Exception
            Console.WriteLine("Error decoding URL: " & ex.Message)
            ' デコードに失敗した場合、元の文字列そのまま
            Return encodedString
        End Try
    End Function

    Private Sub DownloadFromUrl(url As String)
        Try
            Dim fileName As String = Path.GetFileName(url)
            Response.Clear()
            Response.Buffer = False
            Response.ContentType = "application/octet-stream"
            Response.AddHeader("Content-Disposition", "attachment; filename=""" & fileName & """")

            Using client As New WebClient()
                ' 認証情報
                Dim username As String = DBServerAuthUserId
                Dim password As String = DBServerAuthUserPass
                Dim credentials As String = Convert.ToBase64String(Encoding.ASCII.GetBytes(username & ":" & password))
                client.Headers("Authorization") = "Basic " & credentials

                'ダウンロード
                Dim fileData As Byte() = client.DownloadData(url)

                Response.AddHeader("Content-Length", fileData.Length.ToString())
                Response.OutputStream.Write(fileData, 0, fileData.Length)

                Response.Flush()
                Response.Close()
            End Using
        Catch ex As WebException

            Dim errorResponse As HttpWebResponse = TryCast(ex.Response, HttpWebResponse)
            If errorResponse IsNot Nothing Then
                Select Case errorResponse.StatusCode
                    Case HttpStatusCode.Unauthorized
                        Response.Write("<script>alert('認証に失敗しました。ユーザーIDとパスワードを確認してください。');</script>")
                    Case HttpStatusCode.NotFound
                        Response.Write("<script>alert('指定されたファイルが見つかりません。');</script>")
                    Case Else
                        Response.Write(String.Format("<script>alert('ファイルのダウンロードに失敗しました: {0}');</script>", ex.Message))
                End Select
            Else
                Response.Write(String.Format("<script>alert('ネットワークエラーが発生しました: {0}');</script>", ex.Message))
            End If
        Catch ex As Exception
            ' その他例外
            Response.Write(String.Format("<script>alert('エラーが発生しました: {0}');</script>", ex.Message))
        End Try
    End Sub

#End Region

End Class
