from qgis.PyQt import uic, QtWidgets
from qgis.PyQt.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
    QWidget, QGraphicsScene, QGraphicsPolygonItem, QGraphicsLineItem, QSizePolicy,
    QMessageBox, QTableWidgetItem, QHeaderView, QAbstractItemView, QComboBox, QLabel,
    QFrame, QGraphicsDropShadowEffect, QTabWidget, QScrollArea, QTextBrowser, QApplication)
from qgis.PyQt.QtGui import QPolygonF, QPen, QColor, QPainter, QIntValidator, QRegExpValidator, QFont, QPixmap, QDrag, QCursor
from qgis.PyQt.QtCore import Qt, QPointF, pyqtSignal, QVariant, QBuffer, QIODevice, QRegExp, QMimeData, QTimer
import os
import math
from shapely.geometry import Polygon
from math import sin, cos, radians
from qgis.core import (
    QgsPointXY,
    QgsGeometry,
    QgsFeature,
    QgsVectorLayer,
    QgsProject,
    QgsCoordinateReferenceSystem,
    QgsCoordinateTransform,
    QgsFields,
    QgsField,
    QgsWkbTypes,
    QgsApplication,
    QgsRectangle
)
from qgis.gui import QgsMapCanvas, QgsProjectionSelectionDialog
from qgis.core import QgsFillSymbol

# Attempt to import TiePointSelectorDialog, handle potential ImportError later if the file is missing
try:
    from .tie_point_selector_dialog import TiePointSelectorDialog
except ImportError:
    TiePointSelectorDialog = None
    print("Warning: tie_point_selector_dialog.py not found. Tie point selection functionality will be disabled.")

# Make sure shapely is installed in your QGIS environment
# You might need to install it using QGIS's Python terminal or OSGeo4W shell:
# pip install shapely
try:
    from shapely.geometry import Polygon
except ImportError:
    Polygon = None
    print("Warning: shapely library not found. WKT generation functionality will be disabled.")

# Import LLM OCR dialog
try:
    from .llm_ocr_dialog import LLMOCRDialog
    OCR_AVAILABLE = True
except ImportError:
    OCR_AVAILABLE = False

FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(os.path.dirname(__file__)), 'forms', 'title_plotter_dialog_base.ui'))

# Modern Light Teal Theme Stylesheet
MODERN_STYLESHEET = """
/* Main Dialog */
QDialog {
    background-color: #f1fcfb;
    color: #06292d;
    font-family: 'Segoe UI', Arial, sans-serif;
    font-size: 8pt;
}

/* Labels */
QLabel {
    color: #06292d;
    font-size: 8pt;
    background-color: transparent;
}

/* Input Fields */
QLineEdit {
    background-color: #ffffff;
    border: 2px solid #16474b;
    border-radius: 8px;
    padding: 6px 10px;
    color: #06292d;
    font-size: 8pt;
    selection-background-color: #14575b;
    selection-color: #f1fcfb;
}

QLineEdit:focus {
    border: 2px solid #14575b;
    background-color: #ffffff;
}

QLineEdit:hover {
    border: 2px solid #1a6b70;
}

QLineEdit::placeholder {
    color: #5a8a8d;
}

/* Primary Buttons */
QPushButton {
    background-color: #14575b;
    border: none;
    border-radius: 8px;
    padding: 6px 14px;
    color: #f1fcfb;
    font-size: 8pt;
    font-weight: bold;
    min-height: 18px;
}

QPushButton:hover {
    background-color: #1a6b70;
}

QPushButton:pressed {
    background-color: #0f4548;
}

QPushButton:disabled {
    background-color: #a8d4d6;
    color: #5a8a8d;
}

/* Secondary/Small Buttons (+ and -) */
QPushButton[cssClass="secondary"] {
    background-color: #16474b;
    border-radius: 6px;
    padding: 4px;
    min-width: 24px;
    min-height: 24px;
    font-size: 10pt;
    font-weight: bold;
}

QPushButton[cssClass="secondary"]:hover {
    background-color: #1a6b70;
}

QPushButton[cssClass="secondary"]:pressed {
    background-color: #0f4548;
}

/* Accent Buttons */
QPushButton[cssClass="accent"] {
    background-color: #16474b;
    border: 2px solid #14575b;
}

QPushButton[cssClass="accent"]:hover {
    background-color: #1a6b70;
    border: 2px solid #1a6b70;
}

/* Scroll Area */
QScrollArea {
    background-color: #f1fcfb;
    border: 2px solid #16474b;
    border-radius: 10px;
}

QScrollArea > QWidget > QWidget {
    background-color: #f1fcfb;
}

QScrollBar:vertical {
    background-color: #e0f5f3;
    width: 12px;
    border-radius: 6px;
    margin: 2px;
}

QScrollBar::handle:vertical {
    background-color: #14575b;
    border-radius: 5px;
    min-height: 30px;
}

QScrollBar::handle:vertical:hover {
    background-color: #1a6b70;
}

QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
    height: 0px;
}

QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
    background: none;
}

/* Tool Tips */
QToolTip {
    background-color: #14575b;
    color: #f1fcfb;
    border: 1px solid #16474b;
    border-radius: 4px;
    padding: 4px 8px;
}

/* Message Box */
QMessageBox {
    background-color: #f1fcfb;
}

QMessageBox QLabel {
    color: #06292d;
}

QMessageBox QPushButton {
    min-width: 80px;
}
"""

# Bearing Row Input Field Stylesheet (for standalone inputs)
BEARING_INPUT_STYLE = """
QLineEdit {
    background-color: #ffffff;
    border: 2px solid #16474b;
    border-radius: 6px;
    padding: 4px 6px;
    color: #06292d;
    font-size: 8pt;
    font-weight: bold;
}

QLineEdit:focus {
    border: 2px solid #14575b;
    background-color: #ffffff;
}

QLineEdit:hover {
    border: 2px solid #1a6b70;
}
"""

# Grouped Input Style (for inputs inside grouped frame)
GROUPED_INPUT_STYLE = """
QLineEdit {
    background-color: transparent;
    border: none;
    border-radius: 0px;
    padding: 4px 6px;
    color: #06292d;
    font-size: 8pt;
    font-weight: bold;
}
QLineEdit:focus {
    background-color: rgba(20, 87, 91, 0.1);
}
"""

# Error Input Style (for standalone inputs)
ERROR_INPUT_STYLE = """
QLineEdit {
    background-color: #f1fcfb;
    border: 2px solid #d97d85;
    border-radius: 6px;
    padding: 4px 6px;
    color: #9b4a52;
    font-size: 8pt;
    font-weight: bold;
}
"""

# Error Input Style (for grouped inputs)
GROUPED_ERROR_INPUT_STYLE = """
QLineEdit {
    background-color: rgba(217, 125, 133, 0.1);
    border: none;
    border-radius: 0px;
    padding: 4px 6px;
    color: #9b4a52;
    font-size: 8pt;
    font-weight: bold;
}
"""

# Drag Handle Style
DRAG_HANDLE_STYLE = """
QLabel {
    color: #14575b;
    font-size: 12pt;
    font-weight: bold;
    background-color: transparent;
    padding: 0px 2px;
}
QLabel:hover {
    color: #1a6b70;
}
"""

# Drop Indicator Style
DROP_INDICATOR_STYLE = """
QFrame {
    background-color: #14575b;
    border: none;
    border-radius: 2px;
}
"""

def bearing_to_azimuth(direction_ns, degrees, minutes, direction_ew):
    """Convert bearing to azimuth in degrees using Excel's method."""
    angle = int(degrees) + int(minutes) / 60
    if direction_ns == "N" and direction_ew == "E":
        return angle
    elif direction_ns == "S" and direction_ew == "E":
        return 180 - angle
    elif direction_ns == "S" and direction_ew == "W":
        return 180 + angle
    elif direction_ns == "N" and direction_ew == "W":
        return 360 - angle
    else:
        raise ValueError("Invalid bearing direction combination.")

def calculate_deltas(ns, deg, minute, ew, distance):
    """Calculate latitude and departure deltas for a single bearing line with correct signs."""
    angle_degrees = deg + (minute / 60)
    angle_radians = math.radians(angle_degrees)

    delta_lat = distance * math.cos(angle_radians)
    delta_dep = distance * math.sin(angle_radians)

    # Apply sign based on direction
    if ns.upper() == 'S':
        delta_lat *= -1
    if ew.upper() == 'W':
        delta_dep *= -1

    return round(delta_lat, 3), round(delta_dep, 3) # Round to 3 decimal places

def generate_coordinates(tie_easting, tie_northing, bearing_rows):
    """Generate coordinates using Excel's cumulative delta method."""
    coords = []

    current_e = tie_easting
    current_n = tie_northing

    for i, row in enumerate(bearing_rows):
        try:
            ns = row.directionInput.text().strip().upper()
            deg = int(row.degreesInput.text().strip())
            min_ = int(row.minutesInput.text().strip())
            ew = row.quadrantInput.text().strip().upper()
            dist = float(row.distanceInput.text().strip().replace(",", "."))

            # Validate degrees and minutes
            if deg < 0 or deg > 90:
                raise ValueError(f"Degrees must be between 0 and 90 (got {deg})")
            if min_ < 0 or min_ > 59:
                raise ValueError(f"Minutes must be between 0 and 59 (got {min_})")

        except Exception as e:
            raise ValueError(f"Bearing row {i+1} has invalid input: {e}")

        # Use the new calculate_deltas function
        delta_lat, delta_dep = calculate_deltas(ns, deg, min_, ew, dist)

        current_n += delta_lat
        current_e += delta_dep

        coords.append((current_e, current_n))

    return coords

def calculate_misclosure(tie_easting, tie_northing, final_easting, final_northing):
    """Calculate the misclosure (distance between starting and ending points).

    In a perfectly closed traverse, the misclosure would be 0.
    This is the linear error of closure.
    """
    delta_e = final_easting - tie_easting
    delta_n = final_northing - tie_northing
    return math.sqrt(delta_e**2 + delta_n**2)

def calculate_polygon_area(coords):
    """Calculate the area of a polygon using the Shoelace formula.

    Args:
        coords: List of (easting, northing) tuples forming a closed polygon

    Returns:
        Area in square meters (absolute value)
    """
    if len(coords) < 3:
        return 0.0

    # Use Shapely if available for more robust calculation
    if Polygon is not None:
        try:
            polygon = Polygon(coords)
            return abs(polygon.area)
        except Exception:
            pass

    # Fallback to Shoelace formula
    n = len(coords)
    area = 0.0
    for i in range(n):
        j = (i + 1) % n
        area += coords[i][0] * coords[j][1]
        area -= coords[j][0] * coords[i][1]
    return abs(area) / 2.0


class DropIndicatorWidget(QFrame):
    """Visual indicator for drop position during drag-and-drop."""
    def __init__(self, parent=None):
        super(DropIndicatorWidget, self).__init__(parent)
        self.setStyleSheet(DROP_INDICATOR_STYLE)
        self.setFixedHeight(4)
        self.hide()


class BearingRowWidget(QWidget):
    """Widget for a single bearing input row with delta calculations."""
    def __init__(self, parent=None, is_first_row=False):
        super(BearingRowWidget, self).__init__(parent)
        self.is_first_row = is_first_row
        self.setup_ui()

    def setup_ui(self):
        layout = QHBoxLayout(self)
        layout.setContentsMargins(8, 4, 8, 4)
        layout.setSpacing(6)

        # Add Line Label with modern styling
        self.lineLabel = QLabel("")
        self.lineLabel.setFixedWidth(50)
        self.lineLabel.setStyleSheet("""
            QLabel {
                color: #14575b;
                font-size: 8pt;
                font-weight: bold;
                background-color: transparent;
                padding: 3px;
            }
        """)
        layout.addWidget(self.lineLabel)

        # Create input fields
        self.directionInput = QLineEdit()
        self.degreesInput = QLineEdit()
        self.minutesInput = QLineEdit()
        self.quadrantInput = QLineEdit()
        self.distanceInput = QLineEdit()

        # Set properties
        self.directionInput.setMaxLength(1)
        self.degreesInput.setMaxLength(3)
        self.minutesInput.setMaxLength(2)
        self.quadrantInput.setMaxLength(1)

        # Set fixed widths
        self.directionInput.setFixedWidth(40)
        self.degreesInput.setFixedWidth(50)
        self.minutesInput.setFixedWidth(50)
        self.quadrantInput.setFixedWidth(40)
        self.distanceInput.setFixedWidth(90)

        # Set placeholders
        self.directionInput.setPlaceholderText("N/S")
        self.degreesInput.setPlaceholderText("Deg")
        self.minutesInput.setPlaceholderText("Min")
        self.quadrantInput.setPlaceholderText("E/W")
        self.distanceInput.setPlaceholderText("Distance")

        # Center align text in direction and quadrant inputs
        self.directionInput.setAlignment(Qt.AlignCenter)
        self.degreesInput.setAlignment(Qt.AlignCenter)
        self.minutesInput.setAlignment(Qt.AlignCenter)
        self.quadrantInput.setAlignment(Qt.AlignCenter)

        # Add Validators
        self.directionInput.setValidator(QRegExpValidator(QRegExp("^[NSns]$")))
        self.degreesInput.setValidator(QIntValidator(0, 90, self))
        self.minutesInput.setValidator(QIntValidator(0, 59, self))
        self.quadrantInput.setValidator(QRegExpValidator(QRegExp("^[EWew]$")))

        # Create delta labels with modern styling
        self.deltaLatLabel = QLabel("ΔLat: 0.000")
        self.deltaDepLabel = QLabel("ΔDep: 0.000")
        self.deltaLatLabel.setFixedWidth(90)
        self.deltaDepLabel.setFixedWidth(90)

        delta_label_style = """
            QLabel {
                color: #16474b;
                font-size: 7pt;
                font-family: 'Consolas', 'Monaco', monospace;
                background-color: transparent;
                padding: 2px 4px;
            }
        """
        self.deltaLatLabel.setStyleSheet(delta_label_style)
        self.deltaDepLabel.setStyleSheet(delta_label_style)

        # Create modern styled buttons (smaller to match input height)
        self.add_btn = QPushButton("+")
        self.remove_btn = QPushButton("−")  # Using proper minus sign

        # Modern button styling - smaller size to match input boxes
        add_btn_style = """
            QPushButton {
                background-color: #14575b;
                border: none;
                border-radius: 4px;
                color: #f1fcfb;
                font-size: 9pt;
                font-weight: bold;
                min-width: 22px;
                min-height: 22px;
                max-width: 22px;
                max-height: 22px;
            }
            QPushButton:hover {
                background-color: #1a6b70;
            }
            QPushButton:pressed {
                background-color: #0f4548;
            }
        """

        remove_btn_style = """
            QPushButton {
                background-color: #16474b;
                border: none;
                border-radius: 4px;
                color: #f1fcfb;
                font-size: 9pt;
                font-weight: bold;
                min-width: 22px;
                min-height: 22px;
                max-width: 22px;
                max-height: 22px;
            }
            QPushButton:hover {
                background-color: #1a6b70;
            }
            QPushButton:pressed {
                background-color: #0f4548;
            }
            QPushButton:disabled {
                background-color: #a8d4d6;
                color: #5a8a8d;
            }
        """

        self.add_btn.setStyleSheet(add_btn_style)
        self.remove_btn.setStyleSheet(remove_btn_style)
        self.add_btn.setFixedSize(22, 22)
        self.remove_btn.setFixedSize(22, 22)

        # Create a grouped input container with vertical dividers
        input_group = QFrame()
        input_group.setStyleSheet("""
            QFrame {
                background-color: #f1fcfb;
                border: 2px solid #16474b;
                border-radius: 8px;
            }
        """)
        input_group_layout = QHBoxLayout(input_group)
        input_group_layout.setContentsMargins(0, 0, 0, 0)
        input_group_layout.setSpacing(0)

        # Apply grouped style to all inputs
        for input_field in [self.directionInput, self.degreesInput, self.minutesInput,
                           self.quadrantInput, self.distanceInput]:
            input_field.setStyleSheet(GROUPED_INPUT_STYLE)
            input_field.setFixedHeight(22)

        # Create vertical dividers
        def create_divider():
            divider = QFrame()
            divider.setFixedWidth(1)
            divider.setStyleSheet("background-color: #16474b;")
            return divider

        # Add inputs with dividers to the group
        input_group_layout.addWidget(self.directionInput)
        input_group_layout.addWidget(create_divider())
        input_group_layout.addWidget(self.degreesInput)
        input_group_layout.addWidget(create_divider())
        input_group_layout.addWidget(self.minutesInput)
        input_group_layout.addWidget(create_divider())
        input_group_layout.addWidget(self.quadrantInput)
        input_group_layout.addWidget(create_divider())
        input_group_layout.addWidget(self.distanceInput)

        # Add widgets to main layout
        layout.addWidget(input_group)
        layout.addWidget(self.add_btn)
        layout.addWidget(self.remove_btn)

        # Delta labels are hidden but still functional for calculations
        # They are not added to the layout to save UI space
        self.deltaLatLabel.setVisible(False)
        self.deltaDepLabel.setVisible(False)

        layout.addStretch()

        # Connect signals
        self.distanceInput.textChanged.connect(self.update_deltas)
        self.directionInput.textChanged.connect(self.update_deltas) # Also update deltas on direction change
        self.degreesInput.textChanged.connect(self.update_deltas) # Also update deltas on degrees change
        self.minutesInput.textChanged.connect(self.update_deltas) # Also update deltas on minutes change
        self.quadrantInput.textChanged.connect(self.update_deltas) # Also update deltas on quadrant change
        
        # Add validation signals
        self.degreesInput.textChanged.connect(self.validate_degrees)
        self.minutesInput.textChanged.connect(self.validate_minutes)
        self.directionInput.textChanged.connect(self.auto_capitalize_direction)
        self.quadrantInput.textChanged.connect(self.auto_capitalize_quadrant)
        
        self.add_btn.clicked.connect(self.parent().add_bearing_row)
        
        # Only connect remove button if not first row
        if not self.is_first_row:
            # Store reference to the dialog instance
            dialog = self.parent()
            if isinstance(dialog, TitlePlotterPhilippineLandTitlesDialog):
                self.remove_btn.clicked.connect(lambda _, row=self: dialog.remove_bearing_row(row))
        else:
            self.remove_btn.setEnabled(False)

        # Connect text changed signals to trigger WKT generation
        for input_field in [self.directionInput, self.degreesInput, self.minutesInput, 
                          self.quadrantInput, self.distanceInput]:
            input_field.textChanged.connect(self.parent().generate_wkt)

    def validate_degrees(self):
        """Validate degrees input and update UI accordingly."""
        try:
            value = int(self.degreesInput.text())
            if value > 90:
                self.degreesInput.setStyleSheet(GROUPED_ERROR_INPUT_STYLE)
                self.add_btn.setEnabled(False)
            else:
                self.degreesInput.setStyleSheet(GROUPED_INPUT_STYLE)
                self.add_btn.setEnabled(True)
        except ValueError:
            self.degreesInput.setStyleSheet(GROUPED_INPUT_STYLE)
            self.add_btn.setEnabled(True)

    def validate_minutes(self):
        """Validate minutes input and update UI accordingly."""
        try:
            value = int(self.minutesInput.text())
            if value > 59:
                self.minutesInput.setStyleSheet(GROUPED_ERROR_INPUT_STYLE)
                self.add_btn.setEnabled(False)
            else:
                self.minutesInput.setStyleSheet(GROUPED_INPUT_STYLE)
                self.add_btn.setEnabled(True)
        except ValueError:
            self.minutesInput.setStyleSheet(GROUPED_INPUT_STYLE)
            self.add_btn.setEnabled(True)

    def auto_capitalize_direction(self):
        """Auto-capitalize N/S input."""
        text = self.directionInput.text().upper()
        if text != self.directionInput.text():
            self.directionInput.setText(text)

    def auto_capitalize_quadrant(self):
        """Auto-capitalize E/W input."""
        text = self.quadrantInput.text().upper()
        if text != self.quadrantInput.text():
            self.quadrantInput.setText(text)

    def reset_values(self):
        """Reset all input values to empty and clear styles."""
        self.directionInput.setText("")
        self.degreesInput.setText("")
        self.minutesInput.setText("")
        self.quadrantInput.setText("")
        self.distanceInput.setText("")
        # Reset to grouped input styling
        for input_field in [self.directionInput, self.degreesInput, self.minutesInput,
                           self.quadrantInput, self.distanceInput]:
            input_field.setStyleSheet(GROUPED_INPUT_STYLE)
        self.deltaLatLabel.setText("ΔLat: 0.000")
        self.deltaDepLabel.setText("ΔDep: 0.000")
        self.add_btn.setEnabled(True)

    def update_deltas(self):
        """Update delta values when all fields are filled."""
        try:
            # Check if all fields have values
            if not all([
                self.directionInput.text().strip(),
                self.degreesInput.text().strip(),
                self.minutesInput.text().strip(),
                self.quadrantInput.text().strip(),
                self.distanceInput.text().strip()
            ]):
                return

            # Get values
            ns = self.directionInput.text().strip().upper()
            deg = int(self.degreesInput.text().strip())
            min_ = int(self.minutesInput.text().strip())
            ew = self.quadrantInput.text().strip().upper()
            dist = float(self.distanceInput.text().strip().replace(",", "."))

            # Additional validation for degrees and minutes
            if deg < 0 or deg > 90:
                self.degreesInput.setText("0")  # Reset to 0 if out of range
                deg = 0
            if min_ < 0 or min_ > 59:
                self.minutesInput.setText("0")  # Reset to 0 if out of range
                min_ = 0

            # Calculate deltas using the updated function
            delta_lat, delta_dep = calculate_deltas(ns, deg, min_, ew, dist)

            # Update labels
            self.deltaLatLabel.setText(f"ΔLat: {delta_lat:.3f}")
            self.deltaDepLabel.setText(f"ΔDep: {delta_dep:.3f}")

        except ValueError:
            # Clear labels if calculation fails
            self.deltaLatLabel.setText("ΔLat: 0.000")
            self.deltaDepLabel.setText("ΔDep: 0.000")

class TitlePlotterPhilippineLandTitlesDialog(QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(TitlePlotterPhilippineLandTitlesDialog, self).__init__(parent)
        self.iface = iface
        self.setupUi(self)

        # Enable maximize button on the dialog window
        self.setWindowFlags(
            self.windowFlags() |
            Qt.WindowMinimizeButtonHint |
            Qt.WindowMaximizeButtonHint
        )

        # Apply modern stylesheet to the entire dialog
        self.setStyleSheet(MODERN_STYLESHEET)

        # Set minimum size for proper layout (wider for two-column layout)
        self.setMinimumSize(950, 550)

        # Set modern style for the WKT preview label
        self.labelWKT.setStyleSheet("""
            QLabel {
                background-color: #f1fcfb;
                color: #06292d;
                padding: 8px 10px;
                border-radius: 8px;
                font-family: 'Consolas', 'Monaco', monospace;
                font-size: 7pt;
                border: 2px solid #16474b;
            }
        """)
        self.labelWKT.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)

        # Style the tie point input labels
        self.label.setStyleSheet("""
            QLabel {
                color: #06292d;
                font-size: 8pt;
                font-weight: bold;
                background-color: transparent;
            }
        """)
        self.label_2.setStyleSheet("""
            QLabel {
                color: #06292d;
                font-size: 8pt;
                font-weight: bold;
                background-color: transparent;
            }
        """)

        # Style the Technical Description label
        self.technicalDescriptionLabel.setStyleSheet("""
            QLabel {
                color: #06292d;
                font-size: 9pt;
                font-weight: bold;
                background-color: transparent;
                padding: 6px 0px;
            }
        """)

        # Style the Select Tie Point button
        self.openTiePointDialogButton.setStyleSheet("""
            QPushButton {
                background-color: #14575b;
                border: none;
                border-radius: 8px;
                padding: 6px 12px;
                color: #f1fcfb;
                font-size: 8pt;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #1a6b70;
            }
            QPushButton:pressed {
                background-color: #0f4548;
            }
        """)
        self.openTiePointDialogButton.setText("Select Tie Point")

        # Style the Plot button with prominent styling
        self.plotButton.setStyleSheet("""
            QPushButton {
                background-color: #14575b;
                border: none;
                border-radius: 8px;
                padding: 10px 20px;
                color: #f1fcfb;
                font-size: 9pt;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #1a6b70;
            }
            QPushButton:pressed {
                background-color: #0f4548;
            }
        """)
        self.plotButton.setText("Plot on Map")

        # Initialize bearing rows list
        self.bearing_rows = []

        # Connect signals
        self.openTiePointDialogButton.clicked.connect(self.open_tiepoint_selector)
        self.plotButton.clicked.connect(self.plot_on_map)

        # --- Rearrange Layout ---
        # Get references to widgets loaded from UI
        horizontalLayout_tiepoints = self.horizontalLayout
        technicalDescriptionLabel = self.technicalDescriptionLabel
        scrollArea_bearings = self.scrollArea
        plotButton = self.plotButton

        # Improve tie point layout spacing
        horizontalLayout_tiepoints.setSpacing(12)

        # Remove widgets from the original layout structure loaded by setupUi
        self.verticalLayout.removeWidget(technicalDescriptionLabel)
        self.verticalLayout.removeWidget(scrollArea_bearings)
        self.verticalLayout.removeWidget(plotButton)
        self.verticalLayout.removeWidget(self.labelWKT)
        self.verticalLayout.removeItem(horizontalLayout_tiepoints)

        # Create the OCR button (if available) with modern styling
        if OCR_AVAILABLE:
            self.ocrButton = QPushButton("Upload TCT Image")
            self.ocrButton.setToolTip("Extract bearing data from TCT images using Gemini AI")
            self.ocrButton.clicked.connect(self.open_ocr_dialog)
        else:
            self.ocrButton = QPushButton("Upload TCT Image")
            self.ocrButton.setEnabled(False)
            self.ocrButton.setToolTip("Gemini OCR dialog module could not be loaded.")

        # Style the OCR button with accent color
        self.ocrButton.setStyleSheet("""
            QPushButton {
                background-color: #16474b;
                border: none;
                border-radius: 8px;
                padding: 6px 14px;
                color: #f1fcfb;
                font-size: 8pt;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #1a6b70;
            }
            QPushButton:pressed {
                background-color: #0f4548;
            }
            QPushButton:disabled {
                background-color: #a8d4d6;
                color: #5a8a8d;
            }
        """)

        # Create a styled container frame for the preview canvas section
        preview_container = QFrame()
        preview_container.setFrameShape(QFrame.StyledPanel)
        preview_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        preview_container.setStyleSheet("""
            QFrame {
                background-color: #f1fcfb;
                border: 2px solid #16474b;
                border-radius: 12px;
            }
        """)
        preview_layout = QVBoxLayout(preview_container)
        preview_layout.setContentsMargins(12, 12, 12, 12)
        preview_layout.setSpacing(10)

        # Header label for the preview section
        preview_header = QLabel("Lot Preview")
        preview_header.setStyleSheet("""
            QLabel {
                color: #06292d;
                font-size: 8pt;
                font-weight: bold;
                background-color: transparent;
                border: none;
                padding: 0px;
            }
        """)
        preview_layout.addWidget(preview_header)

        # Initialize QgsMapCanvas for the visual preview with modern styling
        self.previewCanvas = QgsMapCanvas(preview_container)
        self.previewCanvas.setCanvasColor(QColor("#f1fcfb"))
        self.previewCanvas.enableAntiAliasing(True)
        self.previewCanvas.setWheelFactor(1.2)
        self.previewCanvas.setEnabled(True)
        self.previewCanvas.setMinimumHeight(150)
        self.previewCanvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.previewCanvas.setStyleSheet("""
            QgsMapCanvas {
                border: 2px solid #16474b;
                border-radius: 8px;
            }
        """)
        preview_layout.addWidget(self.previewCanvas, 1)  # stretch factor 1 to expand

        # Create a horizontal layout for the zoom and new buttons (inside the container)
        button_layout = QHBoxLayout()
        button_layout.setContentsMargins(0, 0, 0, 0)
        button_layout.setSpacing(8)
        button_layout.addStretch()

        # Modern styled zoom button
        self.zoomToLayerBtn = QPushButton("Zoom to Fit")
        self.zoomToLayerBtn.setFixedHeight(26)
        self.zoomToLayerBtn.setMinimumWidth(100)
        self.zoomToLayerBtn.setStyleSheet("""
            QPushButton {
                background-color: #14575b;
                border: none;
                border-radius: 6px;
                padding: 3px 10px;
                color: #f1fcfb;
                font-size: 8pt;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #1a6b70;
            }
            QPushButton:pressed {
                background-color: #0f4548;
            }
        """)
        self.zoomToLayerBtn.clicked.connect(self.zoom_preview_to_layer)
        button_layout.addWidget(self.zoomToLayerBtn)

        # Modern styled New button
        self.newButton = QPushButton("New Plot")
        self.newButton.setFixedHeight(26)
        self.newButton.setMinimumWidth(70)
        self.newButton.setStyleSheet("""
            QPushButton {
                background-color: #16474b;
                border: none;
                border-radius: 6px;
                padding: 3px 10px;
                color: #f1fcfb;
                font-size: 8pt;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #1a6b70;
            }
            QPushButton:pressed {
                background-color: #0f4548;
            }
        """)
        self.newButton.clicked.connect(self.reset_plotter)
        button_layout.addWidget(self.newButton)

        # Add the button layout to the preview layout (inside the container)
        preview_layout.addLayout(button_layout)

        # --- Create Info Panel for Area and Misclosure ---
        info_panel = QFrame()
        info_panel.setFrameShape(QFrame.StyledPanel)
        info_panel.setStyleSheet("""
            QFrame {
                background-color: #f1fcfb;
                border: 2px solid #16474b;
                border-radius: 12px;
                padding: 4px;
            }
        """)
        info_layout = QHBoxLayout(info_panel)
        info_layout.setContentsMargins(20, 12, 20, 12)
        info_layout.setSpacing(20)

        # Area section with icon
        area_container = QWidget()
        area_container.setStyleSheet("background-color: transparent; border: none;")
        area_layout = QHBoxLayout(area_container)
        area_layout.setContentsMargins(0, 0, 0, 0)
        area_layout.setSpacing(10)

        area_icon = QLabel()
        area_icon_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'icons', 'area.svg')
        area_icon.setPixmap(QPixmap(area_icon_path).scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation))
        area_icon.setStyleSheet("background-color: transparent;")

        area_text_container = QWidget()
        area_text_container.setStyleSheet("background-color: transparent; border: none;")
        area_text_layout = QVBoxLayout(area_text_container)
        area_text_layout.setContentsMargins(0, 0, 0, 0)
        area_text_layout.setSpacing(2)

        area_title = QLabel("AREA")
        area_title.setStyleSheet("""
            QLabel {
                color: #16474B;
                font-size: 7pt;
                font-weight: bold;
                letter-spacing: 1px;
                background-color: transparent;
                border: none;
            }
        """)
        self.areaValueLabel = QLabel("-- sq.m.")
        self.areaValueLabel.setStyleSheet("""
            QLabel {
                color: #16474B;
                font-size: 13pt;
                font-weight: bold;
                background-color: transparent;
                border: none;
            }
        """)
        area_text_layout.addWidget(area_title)
        area_text_layout.addWidget(self.areaValueLabel)

        area_layout.addWidget(area_icon)
        area_layout.addWidget(area_text_container)

        # Separator line
        separator = QFrame()
        separator.setFrameShape(QFrame.VLine)
        separator.setStyleSheet("""
            QFrame {
                background-color: #16474b;
                border: none;
                max-width: 1px;
                min-width: 1px;
            }
        """)

        # Misclosure section with icon
        misclosure_container = QWidget()
        misclosure_container.setStyleSheet("background-color: transparent; border: none;")
        misclosure_layout = QHBoxLayout(misclosure_container)
        misclosure_layout.setContentsMargins(0, 0, 0, 0)
        misclosure_layout.setSpacing(10)

        misclosure_icon = QLabel()
        misclosure_icon_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'icons', 'misclosure.svg')
        misclosure_icon.setPixmap(QPixmap(misclosure_icon_path).scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation))
        misclosure_icon.setStyleSheet("background-color: transparent;")

        misclosure_text_container = QWidget()
        misclosure_text_container.setStyleSheet("background-color: transparent; border: none;")
        misclosure_text_layout = QVBoxLayout(misclosure_text_container)
        misclosure_text_layout.setContentsMargins(0, 0, 0, 0)
        misclosure_text_layout.setSpacing(2)

        misclosure_title = QLabel("MISCLOSURE")
        misclosure_title.setStyleSheet("""
            QLabel {
                color: #16474B;
                font-size: 7pt;
                font-weight: bold;
                letter-spacing: 1px;
                background-color: transparent;
                border: none;
            }
        """)
        self.misclosureValueLabel = QLabel("-- m")
        self.misclosureValueLabel.setStyleSheet("""
            QLabel {
                color: #16474B;
                font-size: 13pt;
                font-weight: bold;
                background-color: transparent;
                border: none;
            }
        """)
        misclosure_text_layout.addWidget(misclosure_title)
        misclosure_text_layout.addWidget(self.misclosureValueLabel)

        misclosure_layout.addWidget(misclosure_icon)
        misclosure_layout.addWidget(misclosure_text_container)

        # Add to info panel layout
        info_layout.addWidget(area_container)
        info_layout.addStretch()
        info_layout.addWidget(separator)
        info_layout.addStretch()
        info_layout.addWidget(misclosure_container)
        # --- End Info Panel ---

        # Set size policy for scroll area responsiveness
        scrollArea_bearings.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # Configure main layout spacing
        self.verticalLayout.setSpacing(12)
        self.verticalLayout.setContentsMargins(16, 16, 16, 16)

        # --- Create Two-Column Layout for Technical Description and Lot Preview ---
        # Create a horizontal layout to hold both columns side by side
        main_content_layout = QHBoxLayout()
        main_content_layout.setSpacing(12)

        # Create a styled container frame for the Technical Description section
        tech_desc_container = QFrame()
        tech_desc_container.setFrameShape(QFrame.StyledPanel)
        tech_desc_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        tech_desc_container.setStyleSheet("""
            QFrame {
                background-color: #f1fcfb;
                border: 2px solid #16474b;
                border-radius: 12px;
            }
        """)
        tech_desc_layout = QVBoxLayout(tech_desc_container)
        tech_desc_layout.setContentsMargins(12, 12, 12, 12)
        tech_desc_layout.setSpacing(10)

        # Update the Technical Description label style to match Lot Preview header
        technicalDescriptionLabel.setStyleSheet("""
            QLabel {
                color: #06292d;
                font-size: 8pt;
                font-weight: bold;
                background-color: transparent;
                border: none;
                padding: 0px;
            }
        """)

        # Update scroll area style to remove its own border (container provides the border)
        scrollArea_bearings.setStyleSheet("""
            QScrollArea {
                background-color: transparent;
                border: none;
                border-radius: 0px;
            }
            QScrollArea > QWidget > QWidget {
                background-color: #f1fcfb;
            }
        """)

        # Add label and scroll area to the container
        tech_desc_layout.addWidget(technicalDescriptionLabel)
        tech_desc_layout.addWidget(scrollArea_bearings, 1)  # stretch factor 1 to expand

        # Add columns to horizontal layout with stretch factors (3:2 ratio for wider left column)
        main_content_layout.addWidget(tech_desc_container, 3)
        main_content_layout.addWidget(preview_container, 2)

        # --- End Two-Column Layout ---

        # --- Create Tab Widget ---
        self.tabWidget = QTabWidget()
        self.tabWidget.setStyleSheet("""
            QTabWidget::pane {
                border: 2px solid #16474b;
                border-radius: 8px;
                border-top-left-radius: 0px;
                background-color: #f1fcfb;
                margin-top: -1px;
            }
            QTabWidget::tab-bar {
                left: 16px;
            }
            QTabBar::tab {
                background-color: #e0f5f3;
                color: #06292d;
                padding: 8px 20px;
                margin-right: 2px;
                border: 2px solid #16474b;
                border-bottom: none;
                border-top-left-radius: 8px;
                border-top-right-radius: 8px;
                font-size: 9pt;
                font-weight: bold;
                min-width: 60px;
            }
            QTabBar::tab:selected {
                background-color: #f1fcfb;
                border-bottom: 2px solid #f1fcfb;
            }
            QTabBar::tab:hover:!selected {
                background-color: #c8ebe8;
            }
        """)

        # --- Create Plot Tab ---
        plot_tab = QWidget()
        plot_tab_layout = QVBoxLayout(plot_tab)
        plot_tab_layout.setContentsMargins(12, 12, 12, 12)
        plot_tab_layout.setSpacing(12)

        # Add widgets/layouts to the Plot tab layout
        plot_tab_layout.addLayout(horizontalLayout_tiepoints)
        plot_tab_layout.addWidget(self.ocrButton)
        plot_tab_layout.addLayout(main_content_layout, 1)  # stretch factor 1 to expand
        plot_tab_layout.addWidget(info_panel)
        # Hide the WKT label to save UI space (still functional in background)
        self.labelWKT.setVisible(False)
        plot_tab_layout.addWidget(self.labelWKT)
        plot_tab_layout.addWidget(plotButton)

        self.tabWidget.addTab(plot_tab, "Plot")

        # --- Create How to Use Tab ---
        how_to_use_tab = self._create_how_to_use_tab()
        self.tabWidget.addTab(how_to_use_tab, "Usage")

        # --- Create About Tab ---
        about_tab = self._create_about_tab()
        self.tabWidget.addTab(about_tab, "About")

        # Add the tab widget to the main vertical layout
        self.verticalLayout.addWidget(self.tabWidget)
        # --- End Tab Widget and Rearrange Layout ---

        # Ensure bearingListLayout exists and is a QVBoxLayout (inside scrollArea_bearings)
        # This is already handled by setupUi, but re-checking doesn't hurt
        self.bearingListLayout = self.scrollAreaWidgetContents.layout()
        if not isinstance(self.bearingListLayout, QVBoxLayout):
             # This case should ideally not happen if UI is correctly set up
            self.bearingListLayout = QVBoxLayout(self.scrollAreaWidgetContents)
            self.bearingListLayout.setAlignment(Qt.AlignTop) # Ensure alignment
            self.bearingListLayout.setContentsMargins(0,0,0,0) # Ensure margins
            self.bearingListLayout.setSpacing(2) # Ensure spacing

        # Set minimum height for the scroll area
        # This is set in UI, but can be enforced here if needed
        # self.scrollArea.setMinimumHeight(300)

        # Set up initial row (this adds to bearingListLayout, which is inside scrollArea)
        self.setup_initial_row()

        # Initialize tie point
        self.tie_point = None

        # Store the last generated WKT
        self.last_wkt = None
        
        # Initialize preview layer (for the QgsMapCanvas)
        self.preview_layer = None

        # Remove the old WKT output widget and Generate WKT button
        # These were removed in a previous step, keeping this check for safety
        if hasattr(self, 'wktOutput'):
            self.wktOutput.setParent(None)
            self.wktOutput.deleteLater()
        if hasattr(self, 'generateWKTButton'):
            self.generateWKTButton.setParent(None)
            self.generateWKTButton.deleteLater()

    def _create_how_to_use_tab(self):
        """Create the How to Use tab with step-by-step instructions."""
        how_to_use_tab = QWidget()
        how_to_use_layout = QVBoxLayout(how_to_use_tab)
        how_to_use_layout.setContentsMargins(20, 20, 20, 20)
        how_to_use_layout.setSpacing(0)

        # Create a scroll area for the content
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setStyleSheet("""
            QScrollArea {
                background-color: #f1fcfb;
                border: none;
            }
            QScrollBar:vertical {
                background-color: #e0f5f3;
                width: 12px;
                border-radius: 6px;
                margin: 2px;
            }
            QScrollBar::handle:vertical {
                background-color: #14575b;
                border-radius: 5px;
                min-height: 30px;
            }
            QScrollBar::handle:vertical:hover {
                background-color: #1a6b70;
            }
            QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
                height: 0px;
            }
        """)

        # Content widget inside scroll area
        content_widget = QWidget()
        content_layout = QVBoxLayout(content_widget)
        content_layout.setContentsMargins(10, 10, 10, 10)
        content_layout.setSpacing(20)

        # --- Header ---
        header_label = QLabel("How to Use Title Plotter PH")
        header_label.setStyleSheet("""
            QLabel {
                color: #14575b;
                font-size: 16pt;
                font-weight: bold;
                background-color: transparent;
            }
        """)
        header_label.setAlignment(Qt.AlignCenter)
        content_layout.addWidget(header_label)

        # --- Step 1: Tie Points Section ---
        tie_point_section = self._create_about_section(
            "Step 1: Set Your Tie Point",
            "The tie point is the starting reference point for plotting your lot. It connects your technical "
            "description to a real-world location.\n\n"
            "OPTION A - Select from Database:\n"
            "1. Click the \"Select Tie Point\" button\n"
            "2. Use the search box to find your tie point by name or monument number\n"
            "3. Browse through regions, provinces, and municipalities to narrow down results\n"
            "4. Click on a tie point row to select it\n"
            "5. Click \"Select\" to confirm - the coordinates will auto-fill\n\n"
            "OPTION B - Manual Entry:\n"
            "1. If you have verified coordinates from a licensed surveyor, enter them directly\n"
            "2. Type the Northing value in the \"Northing\" field\n"
            "3. Type the Easting value in the \"Easting\" field\n"
            "4. Coordinates should be in the local coordinate system (PRS92 or similar)\n\n"
            "TIP: If your title mentions a specific BLLM (Bureau of Lands Location Monument) or MBM "
            "(Municipal Boundary Monument), search for that reference in the tie point selector."
        )
        content_layout.addWidget(tie_point_section)

        # --- Step 2: Upload TCT Image Section ---
        upload_section = self._create_about_section(
            "Step 2: Upload TCT Image (Optional)",
            "This feature uses Google Gemini AI to automatically extract bearing and distance data from "
            "images of your Transfer Certificate of Title (TCT).\n\n"
            "HOW TO USE:\n"
            "1. Click the \"Upload TCT Image\" button\n"
            "2. Enter your Google Gemini API key (first time only - it will be saved locally)\n"
            "3. Click \"Browse\" to select an image of your TCT's technical description\n"
            "4. Supported formats: JPG, PNG, GIF, WebP\n"
            "5. Click \"Parse\" and wait for the AI to extract the data\n"
            "6. Review the extracted bearing lines in the results\n"
            "7. Click \"Done\" to automatically fill in the bearing rows\n\n"
            "TIPS FOR BEST RESULTS:\n"
            "• Take a clear, well-lit photo of the technical description section\n"
            "• Ensure all text is legible and not blurry\n"
            "• Crop the image to show only the bearing and distance information\n"
            "• If results are incorrect, you can manually edit the values after applying\n\n"
            "NOTE: Your API key is stored locally and never shared. Images are sent directly to "
            "Google Gemini for processing."
        )
        content_layout.addWidget(upload_section)

        # --- Step 3: Technical Description Section ---
        tech_desc_section = self._create_about_section(
            "Step 3: Enter Technical Description",
            "The Technical Description area is where you input the bearing and distance data that defines "
            "your lot's boundaries.\n\n"
            "UNDERSTANDING THE INPUT FIELDS:\n"
            "Each row represents one boundary line with these components:\n"
            "• N/S: Direction from North or South (type N or S)\n"
            "• Deg: Degrees of the angle (0-90)\n"
            "• Min: Minutes of the angle (0-59)\n"
            "• E/W: Direction to East or West (type E or W)\n"
            "• Distance: Length of the line in meters\n\n"
            "HOW TO ENTER DATA:\n"
            "1. Start with Line 1 (TP - 1), which goes from the Tie Point to Corner 1\n"
            "2. Enter the bearing: e.g., \"N 45° 30' E\" becomes N, 45, 30, E\n"
            "3. Enter the distance in meters\n"
            "4. Click the \"+\" button to add another line\n"
            "5. Continue until all boundary lines are entered\n"
            "6. The last line should return to Corner 1 (closing the polygon)\n\n"
            "READING YOUR TITLE:\n"
            "A typical technical description reads like:\n"
            "\"N. 45° 30' E., 25.50 m. to point 2...\"\n"
            "This translates to: N, 45, 30, E, 25.50\n\n"
            "LINE LABELS EXPLAINED:\n"
            "• TP - 1: From Tie Point to Corner 1\n"
            "• 1 - 2: From Corner 1 to Corner 2\n"
            "• 2 - 3: From Corner 2 to Corner 3\n"
            "• ... and so on until the last line returns to Corner 1\n\n"
            "PREVIEW:\n"
            "As you enter data, the \"Lot Preview\" panel shows a real-time visualization of your polygon. "
            "The Area and Misclosure values update automatically.\n\n"
            "MISCLOSURE:\n"
            "Misclosure indicates how accurately the polygon closes. A value close to 0 means the boundary "
            "lines form a proper closed loop. Higher values may indicate input errors or data from the title."
        )
        content_layout.addWidget(tech_desc_section)

        # --- Step 4: Plot on Map Section ---
        plot_section = self._create_about_section(
            "Step 4: Plot on Map",
            "Once your technical description is complete, you can plot the lot on the QGIS map canvas.\n\n"
            "IMPORTANT - PROJECTION REQUIREMENT:\n"
            "The map canvas MUST NOT be in WGS84 (EPSG:4326) projection. Title Plotter uses local "
            "coordinates, not latitude/longitude.\n\n"
            "HOW TO CHANGE YOUR MAP PROJECTION:\n"
            "1. Look at the bottom-right corner of QGIS for the current EPSG code\n"
            "2. Click on the EPSG code to open the Project Properties\n"
            "3. Search for a local Philippine coordinate system, such as:\n"
            "   • EPSG:3123 - PRS92 / Philippines Zone 3\n"
            "   • EPSG:3124 - PRS92 / Philippines Zone 4\n"
            "   • EPSG:3125 - PRS92 / Philippines Zone 5\n"
            "4. Select the appropriate zone for your location and click OK\n\n"

            "PLOTTING YOUR LOT:\n"
            "1. Ensure you have entered at least 3 bearing lines (for a valid polygon)\n"
            "2. Verify the preview looks correct in the Lot Preview panel\n"
            "3. Click \"Plot on Map\"\n"
            "4. A new layer called \"Title Plot Preview\" will appear on your map\n"
            "5. The map will automatically zoom to your plotted lot\n\n"
            "AFTER PLOTTING:\n"
            "• The plotted layer is a temporary memory layer\n"
            "• To save permanently, right-click the layer and select \"Export\" > \"Save Features As...\"\n"
            "• You can overlay the plot on satellite imagery or cadastral maps for verification\n"
            "• Use the \"New Plot\" button to clear and start a new plot"
        )
        content_layout.addWidget(plot_section)

        # --- Tips Section ---
        tips_section = self._create_about_section(
            "Additional Tips",
            "WORKFLOW RECOMMENDATION:\n"
            "1. First, set up your QGIS project with the correct projection\n"
            "2. Load any reference layers (satellite imagery, cadastral maps)\n"
            "3. Then open Title Plotter and enter your data\n"
            "4. Plot and compare with reference data\n\n"
            "COMMON ISSUES:\n"
            "• Plot appears in wrong location: Check tie point coordinates\n"
            "• Plot appears mirrored/rotated: Verify N/S and E/W directions\n"
            "• Large misclosure value: Double-check all bearing and distance entries\n"
            "• \"Invalid Projection\" error: Change map CRS from EPSG:4326\n\n"
            "ACCURACY NOTES:\n"
            "• Results depend on tie point accuracy from the database\n"
            "• For official boundary verification, consult a licensed geodetic engineer\n"
            "• This tool is for visualization purposes only"
        )
        content_layout.addWidget(tips_section)

        # Add stretch to push content to top
        content_layout.addStretch()

        scroll_area.setWidget(content_widget)
        how_to_use_layout.addWidget(scroll_area)

        return how_to_use_tab

    def _create_about_tab(self):
        """Create the About tab with plugin information, disclaimers, and security notice."""
        about_tab = QWidget()
        about_layout = QVBoxLayout(about_tab)
        about_layout.setContentsMargins(20, 20, 20, 20)
        about_layout.setSpacing(0)

        # Create a scroll area for the about content
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setStyleSheet("""
            QScrollArea {
                background-color: #f1fcfb;
                border: none;
            }
            QScrollBar:vertical {
                background-color: #e0f5f3;
                width: 12px;
                border-radius: 6px;
                margin: 2px;
            }
            QScrollBar::handle:vertical {
                background-color: #14575b;
                border-radius: 5px;
                min-height: 30px;
            }
            QScrollBar::handle:vertical:hover {
                background-color: #1a6b70;
            }
            QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
                height: 0px;
            }
        """)

        # Content widget inside scroll area
        content_widget = QWidget()
        content_layout = QVBoxLayout(content_widget)
        content_layout.setContentsMargins(10, 10, 10, 10)
        content_layout.setSpacing(20)

        # --- Plugin Title and Version ---
        title_label = QLabel("Title Plotter PH")
        title_label.setStyleSheet("""
            QLabel {
                color: #14575b;
                font-size: 18pt;
                font-weight: bold;
                background-color: transparent;
            }
        """)
        title_label.setAlignment(Qt.AlignCenter)
        content_layout.addWidget(title_label)

        version_label = QLabel("Version 1.1.0")
        version_label.setStyleSheet("""
            QLabel {
                color: #16474b;
                font-size: 10pt;
                background-color: transparent;
            }
        """)
        version_label.setAlignment(Qt.AlignCenter)
        content_layout.addWidget(version_label)

        # --- Description Section ---
        desc_frame = self._create_about_section(
            "About",
            "Title Plotter helps non-surveyors and professionals plot lots using bearing and distance, "
            "based on tie points. Designed to work with Philippine land titles. Requires no GIS background.\n\n"
            "This plugin simplifies the process of visualizing land parcels from technical descriptions "
            "commonly found in Transfer Certificates of Title (TCT) and other land title documents in the Philippines."
        )
        content_layout.addWidget(desc_frame)

        # --- Developer Section ---
        dev_frame = self._create_about_section(
            "Developer",
            "Author: Isaac Enage\n"
            "Email: isaacenagework@gmail.com\n\n"
            "Homepage: https://isaacenage.xyz/Tools/titleplotterph\n"
            "Repository: https://github.com/isaacenage/TitlePlotterPH\n\n"
            "License: GPL-3.0"
        )
        content_layout.addWidget(dev_frame)

        # --- Disclaimer Section ---
        disclaimer_frame = self._create_about_section(
            "Disclaimer",
            "IMPORTANT: This plugin is designed primarily for plotting Philippine land titles from "
            "technical descriptions. It is intended as a visualization tool and should NOT be used as "
            "the sole basis for legal, surveying, or property boundary decisions.\n\n"
            "KEY LIMITATIONS:\n\n"
            "• Tie Point Accuracy: The accuracy of plotted parcels depends heavily on the accuracy of "
            "monument tie line coordinates. The built-in tie point database is compiled from various sources "
            "and may contain inaccuracies or outdated information.\n\n"
            "• Not a Survey Tool: This plugin does not replace professional land surveying. For official "
            "boundary determinations, always consult a licensed geodetic engineer.\n\n"
            "• Coordinate System: Results are based on local coordinate systems. Discrepancies may occur "
            "when comparing with other coordinate systems or reference frames.\n\n"
            "CORRECTIONS AND CONTRIBUTIONS:\n\n"
            "If you have your own verified tie point coordinates and believe the ones in the database are "
            "incorrect, you may:\n"
            "• Manually input your corrected tie point coordinates using the input fields\n"
            "• Email corrections to isaacenagework@gmail.com for inclusion in future updates\n\n"
            "Your contributions help improve the accuracy of this tool for all users."
        )
        content_layout.addWidget(disclaimer_frame)

        # --- Security Notice Section ---
        security_frame = self._create_about_section(
            "Security & Privacy",
            "API KEY SECURITY:\n\n"
            "Your API keys (such as Gemini API keys for OCR functionality) are stored locally on your "
            "computer and are NEVER transmitted to any server other than the intended API provider.\n\n"
            "• API keys are stored in QGIS settings on your local machine only\n"
            "• No API keys or credentials are sent to the plugin developer or any third party\n"
            "• API keys are used solely for direct communication between your computer and the API provider "
            "(e.g., Google Gemini for OCR processing)\n"
            "• You maintain full control over your API keys and can remove them at any time\n\n"
            "DATA PRIVACY:\n\n"
            "• All calculations and plotting are performed locally on your computer\n"
            "• No land title data, coordinates, or technical descriptions are transmitted externally\n"
            "• Image processing for OCR is sent directly to Google Gemini API (if used) and is subject "
            "to Google's privacy policy\n\n"
            "For questions about security or privacy, contact: isaacenagework@gmail.com"
        )
        content_layout.addWidget(security_frame)

        # Add stretch to push content to top
        content_layout.addStretch()

        scroll_area.setWidget(content_widget)
        about_layout.addWidget(scroll_area)

        return about_tab

    def _create_about_section(self, title, content):
        """Create a styled section frame for the About tab."""
        frame = QFrame()
        frame.setStyleSheet("""
            QFrame {
                background-color: #ffffff;
                border: 2px solid #16474b;
                border-radius: 10px;
            }
        """)

        layout = QVBoxLayout(frame)
        layout.setContentsMargins(16, 12, 16, 12)
        layout.setSpacing(8)

        # Section title
        title_label = QLabel(title)
        title_label.setStyleSheet("""
            QLabel {
                color: #14575b;
                font-size: 11pt;
                font-weight: bold;
                background-color: transparent;
                border: none;
            }
        """)
        layout.addWidget(title_label)

        # Section content
        content_label = QLabel(content)
        content_label.setWordWrap(True)
        content_label.setMinimumWidth(1)  # Allow label to shrink for proper word wrapping
        content_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        content_label.setStyleSheet("""
            QLabel {
                color: #06292d;
                font-size: 9pt;
                background-color: transparent;
                border: none;
                line-height: 1.4;
            }
        """)
        layout.addWidget(content_label)

        # Set frame size policy to expand horizontally
        frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

        return frame

    def setup_initial_row(self):
        """Set up the initial bearing row."""
        row = BearingRowWidget(self, is_first_row=True)
        self.bearingListLayout.addWidget(row)
        self.bearing_rows.append(row)
        self.update_line_labels()

    def add_bearing_row(self):
        """Add a new bearing input row."""
        row = BearingRowWidget(self)
        self.bearingListLayout.addWidget(row)
        self.bearing_rows.append(row)
        self.update_line_labels()

    def remove_bearing_row(self, row_widget):
        """Remove a bearing input row."""
        if len(self.bearing_rows) > 1:  # Keep at least one row
            self.bearingListLayout.removeWidget(row_widget)
            row_widget.deleteLater()
            self.bearing_rows.remove(row_widget)
            self.update_line_labels()

    def update_line_labels(self):
        """Update the line labels based on their index."""
        for i, row in enumerate(self.bearing_rows):
            if i == 0:
                row.lineLabel.setText("TP - 1")
            elif i == len(self.bearing_rows) - 1:
                row.lineLabel.setText(f"{i} - 1")
            else:
                row.lineLabel.setText(f"{i} - {i+1}")

    def get_bearing_data(self):
        """Get all bearing data from the rows"""
        data = []
        for row in self.bearing_rows:
            row_layout = row.layout()
            direction = row_layout.itemAt(0).widget().text().strip().upper()
            degrees = row_layout.itemAt(1).widget().text().strip()
            minutes = row_layout.itemAt(2).widget().text().strip()
            quadrant = row_layout.itemAt(3).widget().text().strip().upper()
            distance = row_layout.itemAt(4).widget().text().strip()
            
            if all([direction, degrees, minutes, quadrant, distance]):
                try:
                    data.append({
                        'direction': direction,
                        'degrees': int(degrees),
                        'minutes': int(minutes),
                        'quadrant': quadrant,
                        'distance': float(distance)
                    })
                except ValueError:
                    continue
        return data

    def draw_preview(self, coords):
        """Draw the polygon preview on the QgsMapCanvas."""
        if not coords or len(coords) < 2:
            return

        # Create a memory layer for the preview
        self.preview_layer = QgsVectorLayer("Polygon?crs=EPSG:4326", "Preview Layer", "memory")
        provider = self.preview_layer.dataProvider()

        # Create polygon geometry
        polygon = QPolygonF([QPointF(x, y) for x, y in coords])
        geometry = QgsGeometry.fromPolygonXY([[QgsPointXY(p.x(), p.y()) for p in polygon]])
        
        # Create and add feature
        feature = QgsFeature()
        feature.setGeometry(geometry)
        provider.addFeatures([feature])
        
        # Update layer extent
        self.preview_layer.updateExtents()
        
        # Set consistent style for the preview layer
        symbol = QgsFillSymbol.createSimple({
            'color': '0,0,0,0',  # Transparent fill
            'outline_color': 'red',
            'outline_width': '1'
        })
        self.preview_layer.renderer().setSymbol(symbol)
        self.preview_layer.triggerRepaint()
        
        # Set layer to canvas and zoom to fit the polygon properly
        self.previewCanvas.setLayers([self.preview_layer])
        self.zoom_preview_to_layer()

    def generate_wkt(self):
        """Generate WKT using Excel's coordinate calculation method."""
        try:
            # Get tie point coordinates
            tie_n = float(self.tiePointNorthingInput.text().strip().replace(",", "."))
            tie_e = float(self.tiePointEastingInput.text().strip().replace(",", "."))

            # Initialize coordinates list and current position
            coords = []
            current_n = tie_n
            current_e = tie_e

            # Track the final position after ALL bearing rows (for misclosure)
            final_n = tie_n
            final_e = tie_e

            # Process all bearing rows except the last one (for polygon vertices)
            for row in self.bearing_rows[:-1]:
                try:
                    # Get values from the row
                    ns = row.directionInput.text().strip().upper()
                    deg = int(row.degreesInput.text().strip())
                    min_ = int(row.minutesInput.text().strip())
                    ew = row.quadrantInput.text().strip().upper()
                    dist = float(row.distanceInput.text().strip().replace(",", "."))

                    # Calculate deltas
                    delta_lat, delta_dep = calculate_deltas(ns, deg, min_, ew, dist)

                    # Update current position
                    current_n += delta_lat
                    current_e += delta_dep

                    # Add to coordinates list
                    coords.append((current_e, current_n))

                except (ValueError, AttributeError) as e:
                    self._clear_info_panel()
                    return

            # Process ALL bearing rows to calculate final position for misclosure
            for row in self.bearing_rows:
                try:
                    ns = row.directionInput.text().strip().upper()
                    deg = int(row.degreesInput.text().strip())
                    min_ = int(row.minutesInput.text().strip())
                    ew = row.quadrantInput.text().strip().upper()
                    dist = float(row.distanceInput.text().strip().replace(",", "."))

                    delta_lat, delta_dep = calculate_deltas(ns, deg, min_, ew, dist)
                    final_n += delta_lat
                    final_e += delta_dep
                except (ValueError, AttributeError):
                    pass  # Skip incomplete rows for misclosure calculation

            # Check if we have enough points for a polygon
            if len(coords) < 3:
                self.labelWKT.setText("Insufficient points for a polygon (minimum 3)")
                self._clear_info_panel()
                # Clear the preview layer as it's not a valid polygon
                if self.preview_layer and self.preview_layer.isValid():
                    QgsProject.instance().removeMapLayer(self.preview_layer)
                    self.preview_layer = None
                    self.previewCanvas.setLayers([])
                    self.previewCanvas.refresh()
                return

            # Create polygon and generate WKT
            # Ensure coordinates are in (Easting, Northing) format for WKT
            wkt_coords = ', '.join([f'{x} {y}' for x, y in coords])
            # Add the starting point to close the polygon
            if coords:
                 wkt_coords += f', {coords[0][0]} {coords[0][1]}'

            self.last_wkt = f"POLYGON (({wkt_coords}))"

            # Update the WKT preview label
            self.labelWKT.setText(self.last_wkt)

            # Update visual preview (draw the polygon on the map canvas)
            self.draw_preview(coords)

            # Calculate and display area
            area = calculate_polygon_area(coords)
            self._update_area_display(area)

            # Calculate and display misclosure
            misclosure = calculate_misclosure(tie_e, tie_n, final_e, final_n)
            self._update_misclosure_display(misclosure)

        except ValueError:
            self.labelWKT.setText("Error: Invalid numeric input")
            self._clear_info_panel()
        except Exception as e:
            self.labelWKT.setText(f"An unexpected error occurred: {str(e)}")
            self._clear_info_panel()

    def _update_area_display(self, area):
        """Update the area display label with formatted value."""
        if area >= 10000:
            hectares = area / 10000
            self.areaValueLabel.setText(f"{hectares:,.4f} ha")
        else:
            self.areaValueLabel.setText(f"{area:,.2f} sq.m.")

        # Teal styling for area value
        self.areaValueLabel.setStyleSheet("""
            QLabel {
                color: #16474B;
                font-size: 13pt;
                font-weight: bold;
                background-color: transparent;
                border: none;
            }
        """)

    def _update_misclosure_display(self, misclosure):
        """Update the misclosure display label with formatted value and color coding."""
        # Format the misclosure value
        if misclosure < 0.01:
            self.misclosureValueLabel.setText(f"{misclosure:.4f} m")
            # Teal for excellent closure
            self.misclosureValueLabel.setStyleSheet("""
                QLabel {
                    color: #16474B;
                    font-size: 13pt;
                    font-weight: bold;
                    background-color: transparent;
                    border: none;
                }
            """)
        elif misclosure < 0.1:
            self.misclosureValueLabel.setText(f"{misclosure:.3f} m")
            # Teal for acceptable closure
            self.misclosureValueLabel.setStyleSheet("""
                QLabel {
                    color: #16474B;
                    font-size: 13pt;
                    font-weight: bold;
                    background-color: transparent;
                    border: none;
                }
            """)
        else:
            self.misclosureValueLabel.setText(f"{misclosure:.2f} m")
            # Teal for poor closure
            self.misclosureValueLabel.setStyleSheet("""
                QLabel {
                    color: #16474B;
                    font-size: 13pt;
                    font-weight: bold;
                    background-color: transparent;
                    border: none;
                }
            """)

    def _clear_info_panel(self):
        """Clear the area and misclosure display labels."""
        self.areaValueLabel.setText("-- sq.m.")
        self.areaValueLabel.setStyleSheet("""
            QLabel {
                color: #16474B;
                font-size: 13pt;
                font-weight: bold;
                background-color: transparent;
                border: none;
            }
        """)
        self.misclosureValueLabel.setText("-- m")
        self.misclosureValueLabel.setStyleSheet("""
            QLabel {
                color: #16474B;
                font-size: 13pt;
                font-weight: bold;
                background-color: transparent;
                border: none;
            }
        """)

    def open_tiepoint_selector(self):
        """Opens the tie point selection dialog."""
        if TiePointSelectorDialog is None:
            QtWidgets.QMessageBox.warning(self, "Dependency Missing", "The tie point selector dialog file (tie_point_selector_dialog.py) was not found.")
            return

        dialog = TiePointSelectorDialog(self)
        if dialog.exec_(): # exec_() returns QDialog.Accepted or QDialog.Rejected
            selected_row = dialog.get_selected_row()
            if selected_row:
                self.tie_point = selected_row
                self.tiePointNorthingInput.setText(str(selected_row.get('northing', '')))
                self.tiePointEastingInput.setText(str(selected_row.get('easting', '')))
                # Update preview after selecting a tie point
                self.generate_wkt()

    def parse_bearing(self, direction, degrees, minutes, quadrant):
        """Parse bearing components into azimuth."""
        try:
            # Convert to integers and validate
            deg = int(degrees)
            min_ = int(minutes)
            
            # Validate degrees and minutes
            if deg < 0 or deg > 90:
                raise ValueError(f"Degrees must be between 0 and 90 (got {deg})")
            if min_ < 0 or min_ > 59:
                raise ValueError(f"Minutes must be between 0 and 59 (got {min_})")
                
            # Calculate azimuth
            angle = deg + (min_ / 60)
            
            if direction.upper() == "N" and quadrant.upper() == "E":
                return angle
            elif direction.upper() == "S" and quadrant.upper() == "E":
                return 180 - angle
            elif direction.upper() == "S" and quadrant.upper() == "W":
                return 180 + angle
            elif direction.upper() == "N" and quadrant.upper() == "W":
                return 360 - angle
            else:
                raise ValueError(f"Invalid bearing direction combination: {direction}{quadrant}")
        except ValueError as e:
            raise ValueError(f"Invalid bearing: {e}")

    def calculate_point(self, start_point, bearing_azimuth, distance):
        """Calculates the next point based on a starting point, azimuth, and distance.
        Bearing azimuth should be in degrees.
        Returns a tuple (x, y) or None if inputs are invalid.
        """
        try:
            # Normalize decimal separator in distance
            distance = float(str(distance).replace(",", "."))
            if bearing_azimuth is None or distance < 0:
                return None
                
            # Convert azimuth from degrees to radians for trigonometric functions
            azimuth_rad = math.radians(bearing_azimuth)
            
            # Calculate displacements (Easting is X, Northing is Y)
            dx = distance * math.sin(azimuth_rad)
            dy = distance * math.cos(azimuth_rad)
            
            next_x = start_point[0] + dx
            next_y = start_point[1] + dy
            
            return (next_x, next_y)
            
        except ValueError:
            # Handle cases where distance conversion fails
            print(f"Invalid distance value: {distance}")
            return None
        except Exception as e:
             print(f"Error calculating point: {e}")
             return None

    def calculate_coordinates(self):
        """Parses bearing/distance inputs from all rows and calculates the polygon coordinates.
        Returns a list of (x, y) tuples or an empty list if inputs are invalid.
        """
        coords = []
        try:
            # Get starting tie point coordinates (Easting, Northing)
            easting_text = self.tiePointEastingInput.text().strip().replace(",", ".")
            northing_text = self.tiePointNorthingInput.text().strip().replace(",", ".")
            
            if not easting_text or not northing_text:
                 self.wktOutput.setPlainText("Error: Tie point coordinates are required.")
                 return []

            start_easting = float(easting_text)
            start_northing = float(northing_text)
            current_point = (start_easting, start_northing)
            coords.append(current_point)

            # Iterate through bearing input rows
            layout = self.bearingListLayout
            if layout is None:
                print("Error: bearingListLayout is not initialized.")
                return []

            for i in range(layout.count()):
                row_item = layout.itemAt(i)
                if row_item and row_item.widget():
                    row_widget = row_item.widget()
                    row_layout = row_widget.layout()
                    
                    if row_layout and row_layout.count() >= 5:
                        # Get values from the QLineEdit widgets in the row
                        direction = row_layout.itemAt(0).widget().text()
                        degrees = row_layout.itemAt(1).widget().text()
                        minutes = row_layout.itemAt(2).widget().text()
                        quadrant = row_layout.itemAt(3).widget().text()
                        # Normalize decimal separator in distance
                        distance = row_layout.itemAt(4).widget().text().strip().replace(",", ".")

                        # Check if essential fields are filled for this row
                        if not any([direction, degrees, minutes, quadrant, distance]):
                            continue
                            
                        if not all([direction, degrees, minutes, quadrant, distance]):
                             self.wktOutput.setPlainText(f"Error: Incomplete bearing input in row {i+1}.")
                             return []

                        # Parse bearing and calculate the next point
                        bearing_azimuth = self.parse_bearing(direction, degrees, minutes, quadrant)
                        
                        if bearing_azimuth is None:
                             self.wktOutput.setPlainText(f"Error: Invalid bearing format in row {i+1}.")
                             return []

                        next_point = self.calculate_point(current_point, bearing_azimuth, distance)

                        if next_point:
                            coords.append(next_point)
                            current_point = next_point
                        else:
                            self.wktOutput.setPlainText(f"Error: Invalid distance value in row {i+1}.")
                            return []

            return coords

        except ValueError:
            self.wktOutput.setPlainText("Error: Invalid numeric input found.")
            return []
        except Exception as e:
            self.wktOutput.setPlainText(f"An unexpected error occurred during coordinate calculation: {e}")
            return []

    def zoom_preview_to_layer(self):
        """Zoom the preview canvas to fit the entire polygon with padding."""
        if self.preview_layer and self.preview_layer.isValid():
            # Get the layer extent
            extent = self.preview_layer.extent()

            if extent.isEmpty():
                return

            # Get canvas dimensions
            canvas_width = self.previewCanvas.width()
            canvas_height = self.previewCanvas.height()

            if canvas_width <= 0 or canvas_height <= 0:
                # Fallback if canvas dimensions are not available yet
                self.previewCanvas.setExtent(extent)
                self.previewCanvas.refresh()
                return

            # Calculate the aspect ratios
            extent_width = extent.width()
            extent_height = extent.height()

            # Handle edge cases where extent has zero width or height (line or point)
            if extent_width <= 0:
                extent_width = extent_height if extent_height > 0 else 1
            if extent_height <= 0:
                extent_height = extent_width if extent_width > 0 else 1

            canvas_aspect = canvas_width / canvas_height
            extent_aspect = extent_width / extent_height

            # Add padding (15% on each side)
            padding_factor = 0.15

            # Calculate the new extent to fit the polygon while maintaining aspect ratio
            if extent_aspect > canvas_aspect:
                # Extent is wider than canvas - fit width, expand height
                new_width = extent_width * (1 + 2 * padding_factor)
                new_height = new_width / canvas_aspect
            else:
                # Extent is taller than canvas - fit height, expand width
                new_height = extent_height * (1 + 2 * padding_factor)
                new_width = new_height * canvas_aspect

            # Calculate the center of the extent
            center_x = extent.center().x()
            center_y = extent.center().y()

            # Create new extent centered on the polygon
            new_extent = QgsRectangle(
                center_x - new_width / 2,
                center_y - new_height / 2,
                center_x + new_width / 2,
                center_y + new_height / 2
            )

            self.previewCanvas.setExtent(new_extent)
            self.previewCanvas.refresh()

    def plot_on_map(self):
        """Plot the polygon on the map canvas."""
        if not self.last_wkt:
            QMessageBox.warning(self, "Error", "No valid polygon to plot.")
            return

        try:
            # Get the map canvas from the main window and check its CRS
            canvas = self.iface.mapCanvas()
            if not canvas:
                QMessageBox.warning(self, "Warning", "Could not access map canvas.")
                return

            canvas_crs = canvas.mapSettings().destinationCrs()

            # Check if the canvas CRS is EPSG:4326 (WGS84)
            if canvas_crs.authid() == "EPSG:4326":
                # Show informative message and open CRS selection dialog
                QMessageBox.information(
                    self,
                    "Select Coordinate System",
                    "The current project is using WGS84 (EPSG:4326) which uses latitude/longitude.\n\n"
                    "Title Plotter requires a local projected coordinate system.\n\n"
                    "Please select an appropriate Philippine coordinate system:\n"
                    "• PRS92 / Philippines Zone 3 (EPSG:3123)\n"
                    "• PRS92 / Philippines Zone 4 (EPSG:3124)\n"
                    "• PRS92 / Philippines Zone 5 (EPSG:3125)"
                )

                # Open CRS selection dialog
                crs_dialog = QgsProjectionSelectionDialog(self)
                crs_dialog.setWindowTitle("Select Project Coordinate System")
                crs_dialog.setCrs(QgsCoordinateReferenceSystem("EPSG:3123"))  # Default to PRS92 Zone 3

                if crs_dialog.exec_():
                    selected_crs = crs_dialog.crs()

                    # Check if user selected a valid non-WGS84 CRS
                    if selected_crs.isValid() and selected_crs.authid() != "EPSG:4326":
                        # Set the project CRS
                        QgsProject.instance().setCrs(selected_crs)
                        canvas_crs = selected_crs
                    else:
                        QMessageBox.warning(
                            self,
                            "Invalid Selection",
                            "Please select a projected coordinate system (not WGS84)."
                        )
                        return
                else:
                    # User cancelled the dialog
                    return

            # Remove existing "Title Plot Preview" layer if it exists
            for layer in QgsProject.instance().mapLayers().values():
                if layer.name() == "Title Plot Preview":
                    QgsProject.instance().removeMapLayer(layer)

            # Create a new memory layer with the canvas CRS
            layer = QgsVectorLayer(f"Polygon?crs={canvas_crs.authid()}", "Title Plot Preview", "memory")

            # Add attribute field for feature identification
            layer.dataProvider().addAttributes([QgsField("name", QVariant.String)])
            layer.updateFields()

            # Create and add feature
            feature = QgsFeature()

            # Parse WKT and create geometry
            geometry = QgsGeometry.fromWkt(self.last_wkt)

            # Validate geometry
            if not geometry or geometry.isEmpty():
                QMessageBox.warning(self, "Invalid Geometry", "The generated polygon is empty or invalid.")
                return

            if not geometry.isGeosValid():
                QMessageBox.warning(self, "Invalid Geometry", "The generated polygon is not valid.")
                return

            # Set geometry and attributes
            feature.setGeometry(geometry)
            feature.setAttributes(["Title Plot"])

            # Add feature to layer
            layer.dataProvider().addFeatures([feature])

            # Update layer extent and add to project
            layer.updateExtents()
            QgsProject.instance().addMapLayer(layer)

            # Set layer style (similar to QuickWKT)
            symbol = QgsFillSymbol.createSimple({
                'color': '255,0,0,50',  # Semi-transparent red
                'outline_color': 'red',
                'outline_width': '1'
            })
            layer.renderer().setSymbol(symbol)
            layer.triggerRepaint()

            # Zoom to the new polygon
            canvas.setExtent(layer.extent())
            canvas.refresh()

        except Exception as e:
            QMessageBox.critical(self, "Error", f"Failed to plot polygon: {str(e)}")

    def open_ocr_dialog(self):
        """Open the LLM OCR dialog for TCT image processing."""
        if not OCR_AVAILABLE:
            QMessageBox.warning(self, "OCR Unavailable",
                               "LLM OCR dialog module could not be loaded.")
            return

        dialog = LLMOCRDialog(self)
        dialog.exec_() 

    def resizeEvent(self, event):
        """Handles resize event for the dialog."""
        super().resizeEvent(event) 

    def reset_plotter(self):
        """Reset all inputs and clear the plotter."""
        # Clear tie point inputs
        self.tiePointNorthingInput.setText("")
        self.tiePointEastingInput.setText("")
        self.tie_point = None

        # Clear all bearing rows except the first one
        while len(self.bearing_rows) > 1:
            self.remove_bearing_row(self.bearing_rows[-1])

        # Reset the first row
        if self.bearing_rows:
            self.bearing_rows[0].reset_values()

        # Clear WKT and preview
        self.labelWKT.setText("")
        self.last_wkt = None
        if self.preview_layer and self.preview_layer.isValid():
            QgsProject.instance().removeMapLayer(self.preview_layer)
            self.preview_layer = None
            self.previewCanvas.setLayers([])
            self.previewCanvas.refresh()

        # Clear area and misclosure info panel
        self._clear_info_panel()