{% extends "base.html" %}

{% block title %}ZOP Kaszubia - Panel Admina - Norda Biznes Hub{% endblock %}

{% block extra_css %}
<style>
    .admin-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: var(--spacing-xl);
    }

    .admin-header h1 {
        font-size: var(--font-size-2xl);
        color: var(--text-primary);
    }

    .admin-actions {
        display: flex;
        gap: var(--spacing-sm);
    }

    .stats-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
        gap: var(--spacing-lg);
        margin-bottom: var(--spacing-xl);
    }

    .stat-card {
        background: var(--surface);
        padding: var(--spacing-lg);
        border-radius: var(--radius-lg);
        box-shadow: var(--shadow);
        cursor: pointer;
        transition: var(--transition);
        border: 2px solid transparent;
        text-decoration: none;
        display: block;
        color: inherit;
    }

    .stat-card:hover {
        transform: translateY(-2px);
        box-shadow: var(--shadow-lg);
    }

    .stat-card.info-only {
        cursor: default;
        opacity: 0.85;
    }

    .stat-card.info-only:hover {
        transform: none;
        box-shadow: var(--shadow);
    }

    .stat-card.active {
        border-color: var(--primary);
        background: var(--primary-light, #f0fdf4);
    }

    .stat-value {
        font-size: var(--font-size-3xl);
        font-weight: 700;
        color: var(--primary);
    }

    .stat-label {
        font-size: var(--font-size-sm);
        color: var(--text-secondary);
    }

    .stat-card.warning .stat-value {
        color: var(--warning);
    }

    .stat-card.success .stat-value {
        color: var(--success);
    }

    .stat-card.danger .stat-value {
        color: var(--danger);
    }

    /* Stats sections (two-row layout) */
    .stats-section {
        margin-bottom: var(--spacing-lg);
    }

    .stats-section-title {
        font-size: var(--font-size-sm);
        font-weight: 600;
        color: var(--text-secondary);
        text-transform: uppercase;
        letter-spacing: 0.05em;
        margin-bottom: var(--spacing-md);
    }

    .stats-section-title small {
        font-weight: 400;
        text-transform: none;
        letter-spacing: normal;
        opacity: 0.8;
    }

    .stats-grid-small {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: var(--spacing-md);
        max-width: 600px;
    }

    .filter-card {
        cursor: pointer;
    }

    .filter-card:hover {
        transform: translateY(-2px);
        box-shadow: var(--shadow-lg);
    }

    /* AI Action button */
    .stat-card.ai-action {
        background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
        color: white;
        border: none;
        font-family: inherit;
    }

    .stat-card.ai-action .stat-value {
        color: white;
    }

    .stat-card.ai-action .stat-label {
        color: rgba(255,255,255,0.9);
    }

    .stat-card.ai-action:hover {
        background: linear-gradient(135deg, #7c3aed 0%, #6d28d9 100%);
    }

    .stat-card.ai-action:disabled {
        opacity: 0.5;
        cursor: not-allowed;
        transform: none;
    }

    .stat-card.ai-action:disabled:hover {
        box-shadow: var(--shadow);
    }

    /* AI evaluation result */
    .ai-result {
        background: #f3e8ff;
        border: 1px solid #c4b5fd;
        color: #6b21a8;
        padding: var(--spacing-sm) var(--spacing-md);
        border-radius: var(--radius);
        font-size: var(--font-size-sm);
    }

    .ai-result.success {
        background: #dcfce7;
        border-color: #86efac;
        color: #166534;
    }

    .ai-result.error {
        background: #fee2e2;
        border-color: #fca5a5;
        color: #991b1b;
    }

    /* AI badge in news list */
    .ai-badge {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 2px 8px;
        border-radius: var(--radius-sm);
        font-size: var(--font-size-xs);
        font-weight: 500;
    }

    .ai-badge.relevant {
        background: #dcfce7;
        color: #166534;
    }

    .ai-badge.not-relevant {
        background: #fee2e2;
        color: #991b1b;
    }

    /* Star rating display */
    .ai-stars {
        display: inline-flex;
        gap: 1px;
        font-size: 11px;
        letter-spacing: -1px;
    }

    .ai-stars .star-filled { color: #f59e0b; }
    .ai-stars .star-empty { color: #d1d5db; }

    .ai-badge.score-5 { background: #dcfce7; color: #166534; }
    .ai-badge.score-4 { background: #d1fae5; color: #047857; }
    .ai-badge.score-3 { background: #fef3c7; color: #92400e; }
    .ai-badge.score-2 { background: #fee2e2; color: #b91c1c; }
    .ai-badge.score-1 { background: #fecaca; color: #991b1b; }

    /* AI Evaluation Modal */
    .modal-icon {
        font-size: 48px;
        text-align: center;
        margin-bottom: var(--spacing-md);
    }

    .modal-icon.spinning {
        animation: spin 2s linear infinite;
    }

    @keyframes spin {
        from { transform: rotate(0deg); }
        to { transform: rotate(360deg); }
    }

    .modal-description {
        text-align: center;
        color: var(--text-primary);
        margin-bottom: var(--spacing-sm);
    }

    .modal-note {
        text-align: center;
        font-size: var(--font-size-sm);
        color: var(--text-secondary);
        margin-bottom: var(--spacing-lg);
    }

    .ai-progress-bar {
        width: 100%;
        height: 8px;
        background: var(--border);
        border-radius: 4px;
        overflow: hidden;
        margin-bottom: var(--spacing-md);
    }

    .ai-progress-fill {
        height: 100%;
        background: linear-gradient(90deg, #8b5cf6, #7c3aed);
        border-radius: 4px;
        transition: width 0.5s ease;
        width: 0%;
    }

    .ai-result-stats {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: var(--spacing-md);
        margin-bottom: var(--spacing-lg);
    }

    .ai-stat-item {
        text-align: center;
        padding: var(--spacing-md);
        background: var(--background);
        border-radius: var(--radius);
    }

    .ai-stat-item .value {
        font-size: var(--font-size-2xl);
        font-weight: 700;
    }

    .ai-stat-item .label {
        font-size: var(--font-size-sm);
        color: var(--text-secondary);
    }

    .ai-stat-item.success .value { color: var(--success); }
    .ai-stat-item.danger .value { color: var(--danger); }
    .ai-stat-item.warning .value { color: var(--warning); }

    #aiResultIcon.success { color: var(--success); }
    #aiResultIcon.error { color: var(--danger); }

    /* Filters bar */
    .filters-bar {
        display: flex;
        gap: var(--spacing-md);
        margin-bottom: var(--spacing-lg);
        flex-wrap: wrap;
        align-items: center;
    }

    .filter-group {
        display: flex;
        align-items: center;
        gap: var(--spacing-xs);
    }

    .filter-group label {
        font-size: var(--font-size-sm);
        color: var(--text-secondary);
    }

    .filter-checkbox {
        display: flex;
        align-items: center;
        gap: var(--spacing-xs);
        padding: var(--spacing-xs) var(--spacing-sm);
        background: var(--background);
        border-radius: var(--radius);
        cursor: pointer;
        font-size: var(--font-size-sm);
    }

    .filter-checkbox input {
        margin: 0;
    }

    .old-news-warning {
        background: #fef3c7;
        color: #92400e;
        padding: var(--spacing-sm) var(--spacing-md);
        border-radius: var(--radius);
        font-size: var(--font-size-sm);
        display: flex;
        align-items: center;
        gap: var(--spacing-sm);
    }

    /* Pagination */
    .pagination {
        display: flex;
        justify-content: center;
        align-items: center;
        gap: var(--spacing-sm);
        margin-top: var(--spacing-lg);
        padding-top: var(--spacing-lg);
        border-top: 1px solid var(--border);
    }

    .pagination a,
    .pagination span {
        padding: var(--spacing-xs) var(--spacing-sm);
        border-radius: var(--radius);
        font-size: var(--font-size-sm);
        text-decoration: none;
        color: var(--text-primary);
    }

    .pagination a {
        background: var(--background);
        border: 1px solid var(--border);
    }

    .pagination a:hover {
        background: var(--border);
    }

    .pagination .current {
        background: var(--primary);
        color: white;
        font-weight: 600;
    }

    .pagination .disabled {
        opacity: 0.5;
        cursor: not-allowed;
    }

    .pagination-info {
        font-size: var(--font-size-sm);
        color: var(--text-secondary);
    }

    /* Old news badge */
    .old-news-badge {
        background: #fef3c7;
        color: #92400e;
        padding: 2px 6px;
        border-radius: var(--radius-sm);
        font-size: var(--font-size-xs);
        font-weight: 500;
    }

    .panel-section {
        background: var(--surface);
        border-radius: var(--radius-lg);
        padding: var(--spacing-lg);
        box-shadow: var(--shadow);
        margin-bottom: var(--spacing-xl);
    }

    .panel-section h2 {
        font-size: var(--font-size-lg);
        margin-bottom: var(--spacing-lg);
        padding-bottom: var(--spacing-md);
        border-bottom: 1px solid var(--border);
    }

    .pending-news-list {
        display: flex;
        flex-direction: column;
        gap: var(--spacing-md);
    }

    .pending-news-item {
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        padding: var(--spacing-md);
        background: var(--background);
        border-radius: var(--radius);
        gap: var(--spacing-md);
    }

    .news-info {
        flex: 1;
        min-width: 0;
    }

    .news-info h4 {
        font-size: var(--font-size-base);
        margin-bottom: var(--spacing-xs);
        word-break: break-word;
    }

    .news-info h4 a {
        color: inherit;
        text-decoration: none;
    }

    .news-info h4 a:hover {
        color: var(--primary);
    }

    .news-meta {
        font-size: var(--font-size-xs);
        color: var(--text-secondary);
        display: flex;
        gap: var(--spacing-md);
    }

    .news-actions {
        display: flex;
        gap: var(--spacing-xs);
        flex-shrink: 0;
    }

    .btn-approve {
        background: var(--success);
        color: white;
    }

    .btn-approve:hover {
        background: #059669;
    }

    .btn-reject {
        background: var(--danger);
        color: white;
    }

    .btn-reject:hover {
        background: #dc2626;
    }

    .projects-table {
        width: 100%;
        border-collapse: collapse;
    }

    .projects-table th,
    .projects-table td {
        padding: var(--spacing-sm) var(--spacing-md);
        text-align: left;
        border-bottom: 1px solid var(--border);
    }

    .projects-table th {
        font-weight: 600;
        color: var(--text-secondary);
        font-size: var(--font-size-sm);
    }

    .status-badge {
        display: inline-block;
        padding: 2px 8px;
        border-radius: var(--radius-sm);
        font-size: var(--font-size-xs);
        font-weight: 500;
    }

    .status-planned { background: #fef3c7; color: #92400e; }
    .status-in_progress { background: #dbeafe; color: #1e40af; }
    .status-completed { background: #dcfce7; color: #166534; }

    .search-section {
        background: linear-gradient(135deg, #059669 0%, #047857 100%);
        color: white;
        padding: var(--spacing-lg);
        border-radius: var(--radius-lg);
        margin-bottom: var(--spacing-xl);
    }

    .search-section h3 {
        margin-bottom: var(--spacing-md);
    }

    .search-form {
        display: flex;
        gap: var(--spacing-sm);
    }

    .search-form input {
        flex: 1;
        padding: var(--spacing-sm) var(--spacing-md);
        border: none;
        border-radius: var(--radius);
        font-size: var(--font-size-base);
    }

    .search-form button {
        padding: var(--spacing-sm) var(--spacing-lg);
        background: white;
        color: var(--primary);
        border: none;
        border-radius: var(--radius);
        font-weight: 600;
        cursor: pointer;
        transition: var(--transition);
    }

    .search-form button:hover {
        background: #f0fdf4;
    }

    .search-form button:disabled {
        opacity: 0.6;
        cursor: not-allowed;
    }

    .fetch-jobs-list {
        display: flex;
        flex-direction: column;
        gap: var(--spacing-sm);
    }

    .fetch-job {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: var(--spacing-sm) var(--spacing-md);
        background: var(--background);
        border-radius: var(--radius-sm);
        font-size: var(--font-size-sm);
    }

    .fetch-job-status {
        padding: 2px 6px;
        border-radius: var(--radius-sm);
        font-size: var(--font-size-xs);
    }

    .fetch-job-status.completed { background: #dcfce7; color: #166534; }
    .fetch-job-status.failed { background: #fee2e2; color: #991b1b; }
    .fetch-job-status.running { background: #dbeafe; color: #1e40af; }

    /* Progress bar */
    .progress-container {
        display: none;
        margin-top: var(--spacing-lg);
        background: rgba(255,255,255,0.1);
        border-radius: var(--radius);
        padding: var(--spacing-md);
    }

    .progress-container.active {
        display: block;
    }

    .progress-header {
        display: flex;
        justify-content: space-between;
        margin-bottom: var(--spacing-sm);
        font-size: var(--font-size-sm);
    }

    .progress-bar-container {
        height: 8px;
        background: rgba(255,255,255,0.2);
        border-radius: 4px;
        overflow: hidden;
        margin-bottom: var(--spacing-md);
    }

    .progress-bar-fill {
        height: 100%;
        background: white;
        border-radius: 4px;
        transition: width 0.3s ease;
        width: 0%;
    }

    .progress-steps {
        display: flex;
        flex-direction: column;
        gap: var(--spacing-xs);
        font-size: var(--font-size-xs);
        max-height: 200px;
        overflow-y: auto;
    }

    .progress-step {
        display: flex;
        align-items: center;
        gap: var(--spacing-sm);
        opacity: 0.6;
    }

    .progress-step.active {
        opacity: 1;
        font-weight: 600;
    }

    .progress-step.completed {
        opacity: 1;
    }

    .progress-step-icon {
        width: 16px;
        height: 16px;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .progress-step.active .progress-step-icon::before {
        content: "⏳";
    }

    .progress-step.completed .progress-step-icon::before {
        content: "✓";
    }

    .progress-step.pending .progress-step-icon::before {
        content: "○";
    }

    .progress-step-count {
        margin-left: auto;
        background: rgba(255,255,255,0.2);
        padding: 2px 6px;
        border-radius: var(--radius-sm);
    }

    /* Source stats */
    .source-stats {
        display: none;
        margin-top: var(--spacing-md);
        padding: var(--spacing-md);
        background: rgba(255,255,255,0.1);
        border-radius: var(--radius);
    }

    .source-stats.active {
        display: block;
    }

    .source-stats h4 {
        margin-bottom: var(--spacing-sm);
        font-size: var(--font-size-sm);
    }

    .source-stats-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
        gap: var(--spacing-sm);
    }

    .source-stat-item {
        display: flex;
        justify-content: space-between;
        padding: var(--spacing-xs) var(--spacing-sm);
        background: rgba(255,255,255,0.1);
        border-radius: var(--radius-sm);
        font-size: var(--font-size-xs);
    }

    .source-stat-item .count {
        font-weight: 700;
    }

    /* News source badges */
    .source-badge {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 2px 8px;
        border-radius: var(--radius-sm);
        font-size: var(--font-size-xs);
        font-weight: 500;
    }

    .source-badge.brave { background: #fff3cd; color: #856404; }
    .source-badge.rss_local_media { background: #d1ecf1; color: #0c5460; }
    .source-badge.rss_government { background: #d4edda; color: #155724; }
    .source-badge.rss_aggregator { background: #e2e3e5; color: #383d41; }
    .source-badge.manual { background: #f8d7da; color: #721c24; }

    .confidence-badge {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 2px 8px;
        border-radius: var(--radius-sm);
        font-size: var(--font-size-xs);
        font-weight: 500;
    }

    .confidence-badge.high { background: #d4edda; color: #155724; }
    .confidence-badge.medium { background: #fff3cd; color: #856404; }
    .confidence-badge.low { background: #f8d7da; color: #721c24; }

    .empty-state {
        text-align: center;
        padding: var(--spacing-xl);
        color: var(--text-secondary);
    }

    /* Modal */
    .modal-overlay {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0,0,0,0.5);
        z-index: 1000;
        align-items: center;
        justify-content: center;
    }

    .modal-overlay.active {
        display: flex;
    }

    .modal {
        background: var(--surface);
        border-radius: var(--radius-lg);
        padding: var(--spacing-xl);
        max-width: 500px;
        width: 90%;
        max-height: 90vh;
        overflow-y: auto;
    }

    .modal h3 {
        margin-bottom: var(--spacing-lg);
    }

    .form-group {
        margin-bottom: var(--spacing-md);
    }

    .form-group label {
        display: block;
        margin-bottom: var(--spacing-xs);
        font-weight: 500;
    }

    .form-group input,
    .form-group textarea,
    .form-group select {
        width: 100%;
        padding: var(--spacing-sm);
        border: 1px solid var(--border);
        border-radius: var(--radius);
        font-size: var(--font-size-base);
    }

    .form-group textarea {
        min-height: 80px;
        resize: vertical;
    }

    .modal-actions {
        display: flex;
        justify-content: flex-end;
        gap: var(--spacing-sm);
        margin-top: var(--spacing-lg);
    }

    @media (max-width: 768px) {
        .admin-header {
            flex-direction: column;
            align-items: flex-start;
            gap: var(--spacing-md);
        }

        .pending-news-item {
            flex-direction: column;
        }

        .news-actions {
            width: 100%;
            justify-content: flex-end;
        }

        .search-form {
            flex-direction: column;
        }
    }

    /* Progress phases (search → filter → AI → save) */
    .progress-phases {
        display: flex;
        gap: var(--spacing-xs);
        margin-bottom: var(--spacing-md);
        flex-wrap: wrap;
    }

    .progress-phase {
        display: flex;
        align-items: center;
        gap: 6px;
        padding: 6px 12px;
        border-radius: var(--radius);
        font-size: var(--font-size-xs);
        background: rgba(255,255,255,0.1);
        opacity: 0.5;
        transition: all 0.3s ease;
    }

    .progress-phase.active {
        opacity: 1;
        background: rgba(255,255,255,0.25);
        animation: pulse 1.5s ease-in-out infinite;
    }

    .progress-phase.completed {
        opacity: 1;
        background: rgba(34, 197, 94, 0.3);
    }

    @keyframes pulse {
        0%, 100% { transform: scale(1); }
        50% { transform: scale(1.02); }
    }

    .progress-phase-icon {
        font-size: 1em;
    }

    /* Search results container */
    .search-results-container {
        margin-top: var(--spacing-lg);
        padding: var(--spacing-lg);
        background: rgba(255,255,255,0.1);
        border-radius: var(--radius-lg);
        animation: fadeIn 0.5s ease;
    }

    @keyframes fadeIn {
        from { opacity: 0; transform: translateY(-10px); }
        to { opacity: 1; transform: translateY(0); }
    }

    .search-results-summary {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
        gap: var(--spacing-md);
        margin-bottom: var(--spacing-lg);
    }

    .summary-stat {
        text-align: center;
        padding: var(--spacing-md);
        background: rgba(255,255,255,0.1);
        border-radius: var(--radius);
    }

    .summary-stat .value {
        font-size: var(--font-size-2xl);
        font-weight: 700;
    }

    .summary-stat .label {
        font-size: var(--font-size-xs);
        opacity: 0.8;
    }

    .summary-stat.success .value { color: #86efac; }
    .summary-stat.warning .value { color: #fde68a; }
    .summary-stat.error .value { color: #fca5a5; }
    .summary-stat.info .value { color: #93c5fd; }

    /* Auto-approved articles section */
    .auto-approved-section {
        margin-top: var(--spacing-lg);
        padding: var(--spacing-md);
        background: rgba(34, 197, 94, 0.15);
        border-radius: var(--radius);
        border: 1px solid rgba(34, 197, 94, 0.3);
    }

    .auto-approved-section h4 {
        margin-bottom: var(--spacing-md);
        font-size: var(--font-size-sm);
    }

    .auto-approved-list {
        display: flex;
        flex-direction: column;
        gap: var(--spacing-xs);
        max-height: 200px;
        overflow-y: auto;
    }

    .auto-approved-item {
        display: flex;
        align-items: center;
        gap: var(--spacing-sm);
        padding: var(--spacing-xs) var(--spacing-sm);
        background: rgba(255,255,255,0.1);
        border-radius: var(--radius-sm);
        font-size: var(--font-size-xs);
    }

    .auto-approved-item .stars {
        color: #fbbf24;
        flex-shrink: 0;
    }

    .auto-approved-item .title {
        flex: 1;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .auto-approved-item .source {
        color: rgba(255,255,255,0.6);
        flex-shrink: 0;
        font-size: 10px;
    }

    /* Refresh countdown */
    .refresh-countdown {
        margin-top: var(--spacing-lg);
        padding: var(--spacing-md);
        background: rgba(255,255,255,0.1);
        border-radius: var(--radius);
        display: flex;
        justify-content: space-between;
        align-items: center;
        font-size: var(--font-size-sm);
    }

    .refresh-countdown strong {
        font-size: var(--font-size-lg);
        color: #fde68a;
    }
</style>
{% endblock %}

{% block content %}
<div class="admin-header">
    <div>
        <h1>Zielony Okręg Przemysłowy Kaszubia</h1>
        <p class="text-muted">Panel zarządzania bazą wiedzy</p>
    </div>
    <div class="admin-actions">
        <a href="{{ url_for('zopk_index') }}" class="btn btn-secondary" target="_blank">Zobacz stronę publiczną</a>
        <a href="{{ url_for('admin_zopk_news') }}" class="btn btn-secondary">Zarządzaj newsami</a>
        <button class="btn btn-primary" onclick="openAddNewsModal()">+ Dodaj news</button>
    </div>
</div>

<!-- Section 1: General stats (info only, not clickable) -->
<div class="stats-section">
    <h3 class="stats-section-title">Baza wiedzy ZOP Kaszubia</h3>
    <div class="stats-grid stats-grid-small">
        <div class="stat-card info-only">
            <div class="stat-value">{{ stats.total_projects }}</div>
            <div class="stat-label">Projektów</div>
        </div>
        <div class="stat-card info-only">
            <div class="stat-value">{{ stats.total_stakeholders }}</div>
            <div class="stat-label">Interesariuszy</div>
        </div>
        <div class="stat-card info-only">
            <div class="stat-value">{{ stats.total_resources }}</div>
            <div class="stat-label">Materiałów</div>
        </div>
    </div>
</div>

<!-- Section 2: News filters (clickable) -->
<div class="stats-section">
    <h3 class="stats-section-title">Filtruj newsy <small>(kliknij aby wybrać)</small></h3>
    <div class="stats-grid stats-grid-small">
        <a href="?status=pending" class="stat-card filter-card warning {{ 'active' if status_filter == 'pending' else '' }}">
            <div class="stat-value">{{ stats.pending_news }}</div>
            <div class="stat-label">Oczekujących</div>
        </a>
        <a href="?status=approved" class="stat-card filter-card success {{ 'active' if status_filter == 'approved' else '' }}">
            <div class="stat-value">{{ stats.approved_news }}</div>
            <div class="stat-label">Zatwierdzonych</div>
        </a>
        <a href="?status=rejected" class="stat-card filter-card danger {{ 'active' if status_filter == 'rejected' else '' }}">
            <div class="stat-value">{{ stats.rejected_news }}</div>
            <div class="stat-label">Odrzuconych</div>
        </a>
    </div>
</div>

<!-- Section 3: AI Evaluation filters -->
<div class="stats-section">
    <h3 class="stats-section-title">Ocena AI (Gemini) <small>(kliknij aby wybrać)</small></h3>

    <!-- AI Model Info Banner -->
    <div class="ai-model-info" style="background: linear-gradient(135deg, #e0f2fe 0%, #bae6fd 100%); border: 1px solid #7dd3fc; border-radius: var(--radius); padding: var(--spacing-sm) var(--spacing-md); margin-bottom: var(--spacing-md); font-size: var(--font-size-sm);">
        <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--spacing-xs);">
            <div>
                <strong>🤖 Model:</strong> <code style="background: #fff; padding: 2px 6px; border-radius: 4px;">gemini-2.5-flash-lite</code>
            </div>
            <div>
                <strong>📅 Prompt v2:</strong> 2026-01-15
            </div>
            <div title="Via Pomerania, S6, Droga Czerwona, Pakt Bezpieczeństwa, NORDA, Deklaracja Bałtycka">
                <strong>✅ Nowe tematy:</strong> +7 projektów infrastrukturalnych
            </div>
        </div>
    </div>
    <div class="stats-grid" style="grid-template-columns: repeat(4, 1fr); max-width: 800px;">
        <a href="?status=ai_relevant" class="stat-card filter-card success {{ 'active' if status_filter == 'ai_relevant' else '' }}">
            <div class="stat-value">{{ stats.ai_relevant }}</div>
            <div class="stat-label">Pasuje wg AI</div>
        </a>
        <a href="?status=ai_not_relevant" class="stat-card filter-card danger {{ 'active' if status_filter == 'ai_not_relevant' else '' }}">
            <div class="stat-value">{{ stats.ai_not_relevant }}</div>
            <div class="stat-label">Nie pasuje wg AI</div>
        </a>
        <a href="?status=ai_not_evaluated" class="stat-card filter-card warning {{ 'active' if status_filter == 'ai_not_evaluated' else '' }}">
            <div class="stat-value">{{ stats.ai_not_evaluated }}</div>
            <div class="stat-label">Nieocenione</div>
        </a>
        <button type="button" class="stat-card filter-card ai-action" onclick="evaluateWithAI()" id="aiEvalBtn" {% if stats.ai_not_evaluated == 0 %}disabled{% endif %} title="Gemini AI oceni {{ stats.ai_not_evaluated }} nieocenionych newsów">
            <div class="stat-value" style="font-size: var(--font-size-xl);">🤖</div>
            <div class="stat-label">AI: Oceń {{ stats.ai_not_evaluated }}</div>
        </button>
    </div>

    {% if stats.ai_missing_score > 0 %}
    <div class="stats-grid" style="grid-template-columns: repeat(2, 1fr); max-width: 400px; margin-top: var(--spacing-md);">
        <div class="stat-card warning info-only">
            <div class="stat-value">{{ stats.ai_missing_score }}</div>
            <div class="stat-label">Brak gwiazdek</div>
        </div>
        <button type="button" class="stat-card filter-card ai-action" onclick="reevaluateScores()" id="aiRescoreBtn" title="Gemini AI przeoceni {{ stats.ai_missing_score }} newsów i doda oceny 1-5 gwiazdek">
            <div class="stat-value" style="font-size: var(--font-size-xl);">🤖⭐</div>
            <div class="stat-label">AI: Dodaj gwiazdki</div>
        </button>
    </div>
    {% endif %}

    <!-- Re-evaluate low score news with key topics (Via Pomerania, NORDA, etc.) -->
    <div class="stats-grid" style="grid-template-columns: repeat(1, 1fr); max-width: 400px; margin-top: var(--spacing-md);">
        <button type="button" class="stat-card filter-card ai-action" onclick="reevaluateLowScores()" id="aiReevalLowBtn" title="Re-ewaluacja newsów z oceną 1-2★ zawierających nowe tematy (Via Pomerania, NORDA, S6...)">
            <div class="stat-value" style="font-size: var(--font-size-xl);">🔄⭐</div>
            <div class="stat-label">Re-ewaluuj niskie oceny (Via Pomerania, NORDA...)</div>
        </button>
    </div>

    <div id="aiEvalResultLegacy" style="margin-top: var(--spacing-md); display: none;"></div>
</div>

<!-- Old news warning -->
{% if stats.old_news > 0 and not show_old %}
<div class="old-news-warning">
    <span>⚠️</span>
    <span><strong>{{ stats.old_news }} newsów</strong> z przed 2024 roku zostało ukrytych (ZOP Kaszubia powstał w 2024).
    <a href="?status={{ status_filter }}&show_old=true">Pokaż wszystkie</a> lub
    <a href="#" onclick="rejectOldNews(); return false;">odrzuć wszystkie stare</a>.</span>
</div>
{% endif %}

<!-- Search Section -->
<div class="search-section">
    <h3>Wyszukaj nowe artykuły</h3>
    <p style="opacity: 0.9; margin-bottom: var(--spacing-md); font-size: var(--font-size-sm);">Multi-source search: Brave API, RSS (trojmiasto.pl, Dziennik Bałtycki), Google News, gov.pl</p>
    <div class="search-form">
        <input type="text" id="searchQuery" value="Zielony Okręg Przemysłowy Kaszubia" placeholder="Wpisz zapytanie...">
        <button type="button" onclick="searchNews()" id="searchBtn">Szukaj artykułów</button>
    </div>

    <!-- Progress Container -->
    <div class="progress-container" id="progressContainer">
        <div class="progress-header">
            <span id="progressStatus">Inicjalizacja...</span>
            <span id="progressPercent">0%</span>
        </div>
        <div class="progress-bar-container">
            <div class="progress-bar-fill" id="progressBar"></div>
        </div>
        <div class="progress-phases" id="progressPhases">
            <!-- Phases will be rendered by JS -->
        </div>
        <div class="progress-steps" id="progressSteps"></div>
    </div>

    <!-- Results Container (shown after completion) -->
    <div class="search-results-container" id="searchResultsContainer" style="display: none;">
        <!-- Summary Stats -->
        <div class="search-results-summary" id="searchResultsSummary"></div>

        <!-- Auto-approved articles list -->
        <div class="auto-approved-section" id="autoApprovedSection" style="display: none;">
            <h4>✅ Artykuły automatycznie zaakceptowane (3+★)</h4>
            <div class="auto-approved-list" id="autoApprovedList"></div>
        </div>

        <!-- Detailed Statistics Section -->
        <div class="detailed-stats-section" id="detailedStatsSection" style="margin-top: var(--spacing-lg); display: none;">
            <h4 style="margin-bottom: var(--spacing-sm); font-size: var(--font-size-sm); color: var(--text-secondary);">
                📊 Szczegóły procesu
            </h4>
            <div class="detailed-stats-grid" id="detailedStatsGrid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--spacing-sm);"></div>
        </div>

        <!-- AI Rejected Articles Section -->
        <div class="ai-rejected-section" id="aiRejectedSection" style="display: none; margin-top: var(--spacing-lg);">
            <h4 style="color: #ef4444;">❌ Artykuły odrzucone przez AI</h4>
            <div class="ai-rejected-list" id="aiRejectedList" style="max-height: 200px; overflow-y: auto;"></div>
        </div>

        <!-- OK Button to close -->
        <div class="results-actions" style="margin-top: var(--spacing-xl); text-align: center; padding-top: var(--spacing-lg); border-top: 1px solid var(--border);">
            <button type="button" class="btn btn-primary btn-lg" onclick="location.reload()" style="padding: var(--spacing-md) var(--spacing-2xl); font-size: var(--font-size-lg);">
                ✓ OK - Zamknij i odśwież
            </button>
            <p style="margin-top: var(--spacing-sm); font-size: var(--font-size-xs); color: var(--text-secondary);">
                Kliknij aby zamknąć okno wyników i odświeżyć listę newsów
            </p>
        </div>
    </div>

    <div id="searchResult" style="margin-top: var(--spacing-md); display: none;"></div>
</div>

<!-- News List -->
<div class="panel-section">
    <h2>
        {% if status_filter == 'pending' %}Newsy oczekujące na moderację
        {% elif status_filter == 'approved' %}Newsy zatwierdzone
        {% elif status_filter == 'rejected' %}Newsy odrzucone
        {% elif status_filter == 'ai_relevant' %}🤖 Newsy pasujące wg AI
        {% elif status_filter == 'ai_not_relevant' %}🤖 Newsy NIE pasujące wg AI
        {% else %}Wszystkie newsy{% endif %}
        ({{ total_news_filtered }})
    </h2>

    {% if news_items %}
    <div class="pending-news-list">
        {% for news in news_items %}
        <div class="pending-news-item" id="news-{{ news.id }}">
            <div class="news-info">
                <h4><a href="{{ news.url }}" target="_blank" rel="noopener">{{ news.title }}</a></h4>
                <div class="news-meta">
                    {% if news.source_type %}
                    <span class="source-badge {{ news.source_type|replace(' ', '_') }}">
                        {% if news.source_type == 'brave' %}🔍 Brave
                        {% elif news.source_type == 'rss_local_media' %}📰 Media lokalne
                        {% elif news.source_type == 'rss_government' %}🏛️ Rząd
                        {% elif news.source_type == 'rss_aggregator' %}📡 Agregator
                        {% elif news.source_type == 'manual' %}✏️ Ręcznie
                        {% else %}{{ news.source_type }}{% endif %}
                    </span>
                    {% endif %}
                    <span>{{ news.source_name or news.source_domain or '-' }}</span>
                    {% set news_year = news.published_at.year if news.published_at else None %}
                    <span>{{ news.published_at.strftime('%d.%m.%Y') if news.published_at else (news.created_at.strftime('%d.%m.%Y') if news.created_at else '-') }}</span>
                    {% if news_year and news_year < min_year %}
                    <span class="old-news-badge">⚠️ Sprzed {{ min_year }}</span>
                    {% endif %}
                    {% if news.confidence_score %}
                    <span class="confidence-badge {{ 'high' if news.confidence_score >= 4 else ('medium' if news.confidence_score >= 2 else 'low') }}">
                        {% if news.source_count and news.source_count > 1 %}{{ news.source_count }} źródeł{% else %}1 źródło{% endif %}
                    </span>
                    {% endif %}
                    {% if news.status == 'approved' or news.status == 'auto_approved' %}
                    <span class="confidence-badge high">✓ {{ 'Auto' if news.status == 'auto_approved' else '' }}Zatwierdzony</span>
                    {% elif news.status == 'rejected' %}
                    <span class="confidence-badge low">✗ Odrzucony</span>
                    {% endif %}
                    {# AI Evaluation badge with star rating #}
                    {% if news.ai_relevant is not none %}
                    <span class="ai-badge score-{{ news.ai_relevance_score or 3 }}" title="{{ news.ai_evaluation_reason or '' }}">
                        🤖
                        <span class="ai-stars">
                            {% for i in range(1, 6) %}
                                <span class="{{ 'star-filled' if i <= (news.ai_relevance_score or 0) else 'star-empty' }}">★</span>
                            {% endfor %}
                        </span>
                    </span>
                    {% endif %}
                </div>
            </div>
            <div class="news-actions">
                {% if news.status == 'pending' %}
                <button class="btn btn-sm btn-approve" onclick="approveNews({{ news.id }})">Zatwierdź</button>
                <button class="btn btn-sm btn-reject" onclick="rejectNews({{ news.id }})">Odrzuć</button>
                {% elif news.status == 'rejected' %}
                <button class="btn btn-sm btn-approve" onclick="approveNews({{ news.id }})">Przywróć</button>
                {% endif %}
            </div>
        </div>
        {% endfor %}
    </div>

    <!-- Pagination -->
    {% if total_pages > 1 %}
    <div class="pagination">
        {% if current_page > 1 %}
        <a href="?page={{ current_page - 1 }}&status={{ status_filter }}{% if show_old %}&show_old=true{% endif %}">← Poprzednia</a>
        {% else %}
        <span class="disabled">← Poprzednia</span>
        {% endif %}

        {% for p in range(1, total_pages + 1) %}
            {% if p == current_page %}
            <span class="current">{{ p }}</span>
            {% elif p == 1 or p == total_pages or (p >= current_page - 2 and p <= current_page + 2) %}
            <a href="?page={{ p }}&status={{ status_filter }}{% if show_old %}&show_old=true{% endif %}">{{ p }}</a>
            {% elif p == current_page - 3 or p == current_page + 3 %}
            <span>...</span>
            {% endif %}
        {% endfor %}

        {% if current_page < total_pages %}
        <a href="?page={{ current_page + 1 }}&status={{ status_filter }}{% if show_old %}&show_old=true{% endif %}">Następna →</a>
        {% else %}
        <span class="disabled">Następna →</span>
        {% endif %}

        <span class="pagination-info">
            ({{ (current_page - 1) * per_page + 1 }}-{{ [current_page * per_page, total_news_filtered]|min }} z {{ total_news_filtered }})
        </span>
    </div>
    {% endif %}
    {% else %}
    <div class="empty-state">
        <p>Brak newsów{% if status_filter != 'all' %} o tym statusie{% endif %}.</p>
    </div>
    {% endif %}
</div>

<!-- AI Knowledge Base -->
<div class="panel-section">
    <h2>🧠 Baza Wiedzy AI</h2>

    <div id="knowledge-stats-loading" class="text-center py-4">
        <span class="spinner"></span> Ładowanie statystyk...
    </div>

    <div id="knowledge-stats-content" style="display: none;">
        <!-- Content Scraping Stats -->
        <div class="stats-section">
            <h3 class="stats-section-title">Scraping treści</h3>
            <div class="stats-grid stats-grid-small">
                <div class="stat-card info-only">
                    <div class="stat-value" id="kb-total-approved">-</div>
                    <div class="stat-label">Zatwierdzonych newsów</div>
                </div>
                <div class="stat-card info-only success">
                    <div class="stat-value" id="kb-scraped">-</div>
                    <div class="stat-label">Zescrapowanych</div>
                </div>
                <div class="stat-card info-only warning">
                    <div class="stat-value" id="kb-pending-scrape">-</div>
                    <div class="stat-label">Oczekuje na scraping</div>
                </div>
                <button class="stat-card filter-card ai-action" onclick="scrapeContent()" id="scrapeBtn" title="Scrapuj treść artykułów">
                    <div class="stat-value" style="font-size: var(--font-size-xl);">📄</div>
                    <div class="stat-label">Scrapuj treść</div>
                </button>
            </div>
        </div>

        <!-- Knowledge Extraction Stats -->
        <div class="stats-section">
            <h3 class="stats-section-title">Ekstrakcja wiedzy (Gemini AI)</h3>
            <div class="stats-grid stats-grid-small">
                <div class="stat-card info-only">
                    <div class="stat-value" id="kb-total-chunks">-</div>
                    <div class="stat-label">Chunks</div>
                </div>
                <div class="stat-card info-only">
                    <div class="stat-value" id="kb-total-facts">-</div>
                    <div class="stat-label">Faktów</div>
                </div>
                <div class="stat-card info-only">
                    <div class="stat-value" id="kb-total-entities">-</div>
                    <div class="stat-label">Encji</div>
                </div>
                <button class="stat-card filter-card ai-action" onclick="extractKnowledge()" id="extractBtn" title="Wyekstrahuj wiedzę z zescrapowanych artykułów">
                    <div class="stat-value" style="font-size: var(--font-size-xl);">🤖</div>
                    <div class="stat-label">Ekstrakcja AI</div>
                </button>
            </div>
        </div>

        <!-- Embeddings Stats -->
        <div class="stats-section">
            <h3 class="stats-section-title">Semantic Search (Embeddings)</h3>
            <div class="stats-grid stats-grid-small">
                <div class="stat-card info-only success">
                    <div class="stat-value" id="kb-with-embeddings">-</div>
                    <div class="stat-label">Z embeddingami</div>
                </div>
                <div class="stat-card info-only warning">
                    <div class="stat-value" id="kb-pending-embeddings">-</div>
                    <div class="stat-label">Bez embeddingów</div>
                </div>
                <button class="stat-card filter-card ai-action" onclick="generateEmbeddings()" id="embeddingsBtn" title="Wygeneruj embeddingi dla semantic search">
                    <div class="stat-value" style="font-size: var(--font-size-xl);">🔍</div>
                    <div class="stat-label">Generuj embeddingi</div>
                </button>
            </div>
        </div>

        <!-- Top Entities -->
        <div class="stats-section" id="top-entities-section" style="display: none;">
            <h3 class="stats-section-title">Najczęściej wymieniane encje</h3>
            <div id="top-entities-list" class="entity-pills"></div>
        </div>

        <!-- Link to detailed dashboard -->
        <div class="stats-section" style="text-align: center; padding-top: var(--spacing-lg);">
            <a href="{{ url_for('admin_zopk_knowledge_dashboard') }}" class="btn btn-primary">
                📊 Szczegółowy panel bazy wiedzy →
            </a>
        </div>
    </div>

    <div id="knowledge-stats-error" style="display: none;" class="alert alert-danger">
        Błąd ładowania statystyk
    </div>
</div>

<!-- Projects -->
<div class="panel-section">
    <h2>Projekty strategiczne</h2>

    {% if projects %}
    <table class="projects-table">
        <thead>
            <tr>
                <th>Nazwa</th>
                <th>Typ</th>
                <th>Status</th>
                <th>Region</th>
            </tr>
        </thead>
        <tbody>
            {% for project in projects %}
            <tr>
                <td>
                    <strong>{{ project.name }}</strong>
                    <br><small class="text-muted">{{ project.slug }}</small>
                </td>
                <td>{{ project.project_type or '-' }}</td>
                <td>
                    <span class="status-badge status-{{ project.status }}">
                        {% if project.status == 'planned' %}Planowany{% elif project.status == 'in_progress' %}W realizacji{% else %}{{ project.status }}{% endif %}
                    </span>
                </td>
                <td>{{ project.region or '-' }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
    {% else %}
    <div class="empty-state">
        <p>Brak projektów.</p>
    </div>
    {% endif %}
</div>

<!-- Recent Fetch Jobs -->
{% if fetch_jobs %}
<div class="panel-section">
    <h2>Ostatnie wyszukiwania</h2>
    <div class="fetch-jobs-list">
        {% for job in fetch_jobs %}
        <div class="fetch-job">
            <div>
                <strong>{{ job.search_query }}</strong>
                <br><small class="text-muted">{{ job.created_at.strftime('%d.%m.%Y %H:%M') if job.created_at else '-' }}</small>
            </div>
            <div>
                Znaleziono: {{ job.results_found or 0 }} | Nowych: {{ job.results_new or 0 }}
            </div>
            <span class="fetch-job-status {{ job.status }}">{{ job.status }}</span>
        </div>
        {% endfor %}
    </div>
</div>
{% endif %}

<!-- AI Evaluation Modal -->
<div class="modal-overlay" id="aiEvalModal">
    <div class="modal">
        <div id="aiEvalConfirm">
            <div class="modal-icon">🤖</div>
            <h3>Ocena AI (Gemini)</h3>
            <p class="modal-description">Czy chcesz uruchomić ocenę AI dla <strong>max 20</strong> z {{ stats.ai_not_evaluated }} nieocenionych newsów?</p>
            <p class="modal-note">Gemini oceni każdy news pod kątem związku z ZOP Kaszubia.<br>
            <strong>Uwaga:</strong> Proces trwa ok. 30-60 sekund (każdy news = osobne zapytanie do AI).</p>
            <div class="modal-actions">
                <button type="button" class="btn btn-secondary" onclick="closeAiEvalModal()">Anuluj</button>
                <button type="button" class="btn btn-primary" onclick="startAiEvaluation()">
                    <span>🚀</span> Rozpocznij ocenę
                </button>
            </div>
        </div>
        <div id="aiEvalProgress" style="display: none;">
            <div class="modal-icon spinning">⚙️</div>
            <h3>Trwa ocena AI...</h3>
            <p class="modal-description" id="aiEvalStatusText">Analizowanie newsów przez Gemini...</p>
            <div class="ai-progress-bar">
                <div class="ai-progress-fill" id="aiProgressFill"></div>
            </div>
            <p class="modal-note" id="aiEvalCounter">Proszę czekać...</p>
        </div>
        <div id="aiEvalResult" style="display: none;">
            <div class="modal-icon" id="aiResultIcon">✓</div>
            <h3 id="aiResultTitle">Ocena zakończona</h3>
            <div class="ai-result-stats" id="aiResultStats"></div>
            <div class="modal-actions">
                <button type="button" class="btn btn-primary" onclick="closeAiEvalModal(); location.reload();">Zamknij i odśwież</button>
            </div>
        </div>
    </div>
</div>

<!-- AI Operations Progress Modal -->
<div class="modal-overlay" id="aiOpsModal">
    <div class="modal modal-wide">
        <div class="modal-header">
            <div class="modal-icon" id="aiOpsIcon">⏳</div>
            <h3 id="aiOpsTitle">Operacja w toku...</h3>
            <button type="button" class="modal-close-btn" id="aiOpsCloseBtn" style="display: none;" onclick="closeAiOpsModal()">×</button>
        </div>

        <!-- Progress Section -->
        <div class="ai-ops-progress">
            <div class="ai-progress-bar">
                <div class="ai-progress-fill" id="aiOpsProgressFill" style="width: 0%;"></div>
            </div>
            <div class="ai-ops-stats">
                <span id="aiOpsPercent">0%</span>
                <span id="aiOpsCounter">0 / 0</span>
            </div>
        </div>

        <!-- Current Operation -->
        <div class="ai-ops-current" id="aiOpsCurrentOp">
            <span class="spinner-small"></span>
            <span id="aiOpsCurrentText">Inicjalizacja...</span>
        </div>

        <!-- Live Log (scrollable) -->
        <div class="ai-ops-log-container">
            <div class="ai-ops-log-header">
                <span>📋 Log operacji</span>
                <span id="aiOpsLogCount">0 wpisów</span>
            </div>
            <div class="ai-ops-log" id="aiOpsLog">
                <!-- Log entries will be added here -->
            </div>
        </div>

        <!-- Summary Stats (shown on complete) -->
        <div class="ai-ops-summary" id="aiOpsSummary" style="display: none;">
            <div class="summary-row">
                <span class="summary-label">✓ Sukces:</span>
                <span class="summary-value" id="aiOpsSummarySuccess">0</span>
            </div>
            <div class="summary-row">
                <span class="summary-label">✗ Błędy:</span>
                <span class="summary-value" id="aiOpsSummaryFailed">0</span>
            </div>
            <div class="summary-row" id="aiOpsSummarySkippedRow" style="display: none;">
                <span class="summary-label">⊘ Pominięto:</span>
                <span class="summary-value" id="aiOpsSummarySkipped">0</span>
            </div>
            <div class="summary-row">
                <span class="summary-label">⏱️ Czas:</span>
                <span class="summary-value" id="aiOpsSummaryTime">0s</span>
            </div>
        </div>

        <!-- Actions -->
        <div class="modal-actions" id="aiOpsActions" style="display: none;">
            <button type="button" class="btn btn-primary" onclick="closeAiOpsModal(); loadKnowledgeStats();">Zamknij i odśwież</button>
        </div>
    </div>
</div>

<style>
/* AI Operations Modal Styles */
.modal-wide {
    max-width: 700px;
    width: 95%;
}

.modal-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 20px;
    position: relative;
}

.modal-header h3 {
    margin: 0;
    flex: 1;
}

.modal-close-btn {
    position: absolute;
    right: 0;
    top: 0;
    background: none;
    border: none;
    font-size: 24px;
    cursor: pointer;
    color: var(--text-muted);
    padding: 5px 10px;
}

.modal-close-btn:hover {
    color: var(--text-primary);
}

.ai-ops-progress {
    margin-bottom: 15px;
}

.ai-ops-stats {
    display: flex;
    justify-content: space-between;
    font-size: 14px;
    margin-top: 8px;
    color: var(--text-muted);
}

#aiOpsPercent {
    font-weight: 600;
    color: var(--color-primary);
}

.ai-ops-current {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 15px;
    background: var(--bg-secondary);
    border-radius: 8px;
    margin-bottom: 15px;
    font-size: 14px;
}

.ai-ops-log-container {
    border: 1px solid var(--border-color);
    border-radius: 8px;
    overflow: hidden;
    margin-bottom: 15px;
}

.ai-ops-log-header {
    display: flex;
    justify-content: space-between;
    padding: 8px 12px;
    background: var(--bg-tertiary);
    font-size: 13px;
    font-weight: 500;
    border-bottom: 1px solid var(--border-color);
}

.ai-ops-log {
    height: 250px;
    overflow-y: auto;
    padding: 10px;
    font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
    font-size: 12px;
    background: var(--bg-primary);
}

.log-entry {
    padding: 4px 8px;
    margin: 2px 0;
    border-radius: 4px;
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.log-entry.processing {
    background: rgba(59, 130, 246, 0.1);
    color: #3b82f6;
}

.log-entry.success {
    background: rgba(34, 197, 94, 0.1);
    color: #22c55e;
}

.log-entry.failed {
    background: rgba(239, 68, 68, 0.1);
    color: #ef4444;
}

.log-entry.skipped {
    background: rgba(234, 179, 8, 0.1);
    color: #eab308;
}

.log-entry.complete {
    background: rgba(168, 85, 247, 0.1);
    color: #a855f7;
    font-weight: 600;
}

.log-time {
    color: var(--text-muted);
    font-size: 11px;
    white-space: nowrap;
}

.log-message {
    flex: 1;
    word-break: break-word;
}

.ai-ops-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 10px;
    padding: 15px;
    background: var(--bg-secondary);
    border-radius: 8px;
    margin-bottom: 15px;
}

.summary-row {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.summary-label {
    font-size: 12px;
    color: var(--text-muted);
}

.summary-value {
    font-size: 24px;
    font-weight: 700;
    color: var(--text-primary);
}

/* Spinning icon animation */
@keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

.modal-icon.spinning {
    animation: spin 2s linear infinite;
}

/* Responsive log height */
@media (max-height: 800px) {
    .ai-ops-log {
        height: 180px;
    }
}
</style>

<!-- Add News Modal -->
<div class="modal-overlay" id="addNewsModal">
    <div class="modal">
        <h3>Dodaj news ręcznie</h3>
        <form id="addNewsForm">
            <div class="form-group">
                <label for="newsTitle">Tytuł *</label>
                <input type="text" id="newsTitle" name="title" required>
            </div>
            <div class="form-group">
                <label for="newsUrl">URL artykułu *</label>
                <input type="url" id="newsUrl" name="url" required placeholder="https://...">
            </div>
            <div class="form-group">
                <label for="newsDescription">Opis</label>
                <textarea id="newsDescription" name="description" placeholder="Krótki opis artykułu..."></textarea>
            </div>
            <div class="form-group">
                <label for="newsSource">Źródło</label>
                <input type="text" id="newsSource" name="source_name" placeholder="np. trojmiasto.pl">
            </div>
            <div class="form-group">
                <label for="newsProject">Projekt</label>
                <select id="newsProject" name="project_id">
                    <option value="">-- Brak --</option>
                    {% for project in projects %}
                    <option value="{{ project.id }}">{{ project.name }}</option>
                    {% endfor %}
                </select>
            </div>
            <div class="modal-actions">
                <button type="button" class="btn btn-secondary" onclick="closeAddNewsModal()">Anuluj</button>
                <button type="submit" class="btn btn-primary">Dodaj</button>
            </div>
        </form>
    </div>
</div>

<!-- Universal Confirm/Alert Modal -->
<div class="modal-overlay" id="confirmModal">
    <div class="modal" style="max-width: 420px;">
        <div style="text-align: center; margin-bottom: var(--spacing-lg);">
            <div class="modal-icon" id="confirmModalIcon">❓</div>
            <h3 id="confirmModalTitle" style="margin-bottom: var(--spacing-sm);">Potwierdzenie</h3>
            <p class="modal-description" id="confirmModalMessage">Czy na pewno chcesz kontynuować?</p>
        </div>
        <!-- Optional input for prompt -->
        <div class="form-group" id="confirmModalInputGroup" style="display: none;">
            <label id="confirmModalInputLabel">Wprowadź wartość:</label>
            <input type="text" id="confirmModalInput" placeholder="">
        </div>
        <div class="modal-actions" style="justify-content: center;">
            <button type="button" class="btn btn-secondary" id="confirmModalCancel">Anuluj</button>
            <button type="button" class="btn btn-primary" id="confirmModalOk">OK</button>
        </div>
    </div>
</div>

<!-- Toast notifications -->
<div id="toastContainer" style="position: fixed; top: 80px; right: 20px; z-index: 1100; display: flex; flex-direction: column; gap: 10px;"></div>

<style>
/* Toast styles */
.toast {
    padding: 12px 20px;
    border-radius: var(--radius);
    background: var(--surface);
    border-left: 4px solid var(--primary);
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    display: flex;
    align-items: center;
    gap: 10px;
    animation: slideIn 0.3s ease;
    max-width: 350px;
}
.toast.success { border-left-color: var(--success); }
.toast.error { border-left-color: var(--error); }
.toast.warning { border-left-color: #f59e0b; }
.toast-icon { font-size: 1.2em; }
.toast-message { flex: 1; }
@keyframes slideIn {
    from { transform: translateX(100%); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}
@keyframes slideOut {
    from { transform: translateX(0); opacity: 1; }
    to { transform: translateX(100%); opacity: 0; }
}

/* Spinner */
.spinner, .spinner-small {
    display: inline-block;
    border: 3px solid var(--border);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}
.spinner {
    width: 24px;
    height: 24px;
}
.spinner-small {
    width: 16px;
    height: 16px;
    border-width: 2px;
}
@keyframes spin {
    to { transform: rotate(360deg); }
}

/* Entity Pills */
.entity-pills {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}
.entity-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-full, 9999px);
    font-size: var(--font-size-sm);
    background: var(--surface-secondary, #f5f5f5);
    border: 1px solid var(--border);
}
.entity-pill small {
    color: var(--text-muted);
}
.entity-pill.entity-company { background: #dbeafe; border-color: #93c5fd; }
.entity-pill.entity-person { background: #fef3c7; border-color: #fcd34d; }
.entity-pill.entity-place { background: #d1fae5; border-color: #6ee7b7; }
.entity-pill.entity-organization { background: #e0e7ff; border-color: #a5b4fc; }
.entity-pill.entity-project { background: #fce7f3; border-color: #f9a8d4; }

/* Text utilities */
.text-center { text-align: center; }
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }

/* Alert */
.alert { padding: var(--spacing-md); border-radius: var(--radius); }
.alert-danger { background: #fef2f2; border: 1px solid #fecaca; color: #dc2626; }
</style>
{% endblock %}

{% block extra_js %}
const csrfToken = '{{ csrf_token() }}';

// ===========================================
// Universal Modal System
// ===========================================
let confirmModalResolve = null;

function showConfirm(message, options = {}) {
    return new Promise((resolve) => {
        confirmModalResolve = resolve;
        const modal = document.getElementById('confirmModal');
        const icon = document.getElementById('confirmModalIcon');
        const title = document.getElementById('confirmModalTitle');
        const msg = document.getElementById('confirmModalMessage');
        const cancelBtn = document.getElementById('confirmModalCancel');
        const okBtn = document.getElementById('confirmModalOk');
        const inputGroup = document.getElementById('confirmModalInputGroup');
        const input = document.getElementById('confirmModalInput');

        icon.textContent = options.icon || '❓';
        title.textContent = options.title || 'Potwierdzenie';
        msg.innerHTML = message;
        cancelBtn.textContent = options.cancelText || 'Anuluj';
        okBtn.textContent = options.okText || 'OK';
        okBtn.className = 'btn ' + (options.okClass || 'btn-primary');

        // Show/hide input for prompt mode
        if (options.showInput) {
            inputGroup.style.display = 'block';
            document.getElementById('confirmModalInputLabel').textContent = options.inputLabel || 'Wprowadź wartość:';
            input.value = options.inputValue || '';
            input.placeholder = options.inputPlaceholder || '';
        } else {
            inputGroup.style.display = 'none';
        }

        // Show/hide cancel button for alert mode
        cancelBtn.style.display = options.alertOnly ? 'none' : '';

        modal.classList.add('active');

        if (options.showInput) {
            setTimeout(() => input.focus(), 100);
        }
    });
}

function closeConfirmModal(result) {
    document.getElementById('confirmModal').classList.remove('active');
    if (confirmModalResolve) {
        confirmModalResolve(result);
        confirmModalResolve = null;
    }
}

// Modal button handlers
document.getElementById('confirmModalOk').addEventListener('click', () => {
    const inputGroup = document.getElementById('confirmModalInputGroup');
    if (inputGroup.style.display !== 'none') {
        closeConfirmModal(document.getElementById('confirmModalInput').value);
    } else {
        closeConfirmModal(true);
    }
});

document.getElementById('confirmModalCancel').addEventListener('click', () => {
    closeConfirmModal(false);
});

document.getElementById('confirmModal').addEventListener('click', (e) => {
    if (e.target.id === 'confirmModal') {
        closeConfirmModal(false);
    }
});

// Keyboard support
document.getElementById('confirmModal').addEventListener('keydown', (e) => {
    if (e.key === 'Escape') closeConfirmModal(false);
    if (e.key === 'Enter' && document.getElementById('confirmModalInputGroup').style.display === 'none') {
        closeConfirmModal(true);
    }
});

// Toast notification system
function showToast(message, type = 'info', duration = 4000) {
    const container = document.getElementById('toastContainer');
    const icons = { success: '✓', error: '✕', warning: '⚠', info: 'ℹ' };

    const toast = document.createElement('div');
    toast.className = `toast ${type}`;
    toast.innerHTML = `
        <span class="toast-icon">${icons[type] || icons.info}</span>
        <span class="toast-message">${message}</span>
    `;
    container.appendChild(toast);

    setTimeout(() => {
        toast.style.animation = 'slideOut 0.3s ease forwards';
        setTimeout(() => toast.remove(), 300);
    }, duration);
}

function openAddNewsModal() {
    document.getElementById('addNewsModal').classList.add('active');
}

function closeAddNewsModal() {
    document.getElementById('addNewsModal').classList.remove('active');
    document.getElementById('addNewsForm').reset();
}

document.getElementById('addNewsForm').addEventListener('submit', async function(e) {
    e.preventDefault();

    const formData = {
        title: document.getElementById('newsTitle').value,
        url: document.getElementById('newsUrl').value,
        description: document.getElementById('newsDescription').value,
        source_name: document.getElementById('newsSource').value,
        project_id: document.getElementById('newsProject').value || null
    };

    try {
        const response = await fetch('{{ url_for("admin_zopk_news_add") }}', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify(formData)
        });

        const data = await response.json();
        if (data.success) {
            closeAddNewsModal();
            showToast('News został dodany', 'success');
            setTimeout(() => location.reload(), 1000);
        } else {
            showToast(data.error || 'Wystąpił błąd', 'error');
        }
    } catch (error) {
        showToast('Błąd połączenia: ' + error.message, 'error');
    }
});

async function approveNews(newsId) {
    const confirmed = await showConfirm('Czy na pewno chcesz zatwierdzić ten news?', {
        icon: '✓',
        title: 'Zatwierdź news',
        okText: 'Zatwierdź',
        okClass: 'btn-success'
    });
    if (!confirmed) return;

    try {
        const response = await fetch(`/admin/zopk/news/${newsId}/approve`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            }
        });

        const data = await response.json();
        if (data.success) {
            document.getElementById(`news-${newsId}`).remove();
            showToast('News został zatwierdzony', 'success');
        } else {
            showToast(data.error || 'Wystąpił błąd', 'error');
        }
    } catch (error) {
        showToast('Błąd połączenia: ' + error.message, 'error');
    }
}

async function rejectNews(newsId) {
    const reason = await showConfirm('Podaj powód odrzucenia (opcjonalnie):', {
        icon: '✕',
        title: 'Odrzuć news',
        showInput: true,
        inputLabel: 'Powód odrzucenia:',
        inputPlaceholder: 'np. Nieistotny artykuł...',
        okText: 'Odrzuć',
        okClass: 'btn-danger'
    });
    if (reason === false) return; // User cancelled

    try {
        const response = await fetch(`/admin/zopk/news/${newsId}/reject`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify({ reason: reason })
        });

        const data = await response.json();
        if (data.success) {
            document.getElementById(`news-${newsId}`).remove();
            showToast('News został odrzucony', 'success');
        } else {
            showToast(data.error || 'Wystąpił błąd', 'error');
        }
    } catch (error) {
        showToast('Błąd połączenia: ' + error.message, 'error');
    }
}

async function rejectOldNews() {
    const minYear = {{ min_year }};
    const confirmed = await showConfirm(
        `Czy na pewno chcesz odrzucić wszystkie newsy sprzed <strong>${minYear}</strong> roku?<br><br>` +
        `<small style="color: var(--text-muted)">ZOP Kaszubia powstał w 2024 roku, więc starsze artykuły najprawdopodobniej nie dotyczą tego projektu.</small>`,
        {
            icon: '🗑️',
            title: 'Odrzuć stare newsy',
            okText: 'Odrzuć wszystkie',
            okClass: 'btn-danger'
        }
    );
    if (!confirmed) {
        return;
    }

    try {
        const response = await fetch('/admin/zopk/news/reject-old', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify({ min_year: minYear })
        });

        const data = await response.json();
        if (data.success) {
            showToast(data.message, 'success', 3000);
            setTimeout(() => location.reload(), 1500);
        } else {
            showToast(data.error || 'Wystąpił błąd', 'error');
        }
    } catch (error) {
        showToast('Błąd połączenia: ' + error.message, 'error');
    }
}

// AI Evaluation Modal functions
function evaluateWithAI() {
    // Open modal instead of confirm()
    document.getElementById('aiEvalModal').classList.add('active');
    // Reset modal state
    document.getElementById('aiEvalConfirm').style.display = 'block';
    document.getElementById('aiEvalProgress').style.display = 'none';
    document.getElementById('aiEvalResult').style.display = 'none';
}

function closeAiEvalModal() {
    document.getElementById('aiEvalModal').classList.remove('active');
}

async function startAiEvaluation() {
    const btn = document.getElementById('aiEvalBtn');
    const progressFill = document.getElementById('aiProgressFill');
    const statusText = document.getElementById('aiEvalStatusText');
    const counter = document.getElementById('aiEvalCounter');

    // Switch to progress view
    document.getElementById('aiEvalConfirm').style.display = 'none';
    document.getElementById('aiEvalProgress').style.display = 'block';

    // Disable button
    btn.disabled = true;
    btn.querySelector('.stat-label').textContent = 'AI pracuje...';

    // Animated progress with better messaging
    let progress = 0;
    let seconds = 0;
    const progressInterval = setInterval(() => {
        progress = Math.min(progress + Math.random() * 8, 95);
        seconds++;
        progressFill.style.width = `${progress}%`;

        // Show elapsed time and encouraging messages
        if (seconds < 30) {
            statusText.textContent = `Gemini analizuje newsy... ${Math.round(progress)}%`;
        } else if (seconds < 60) {
            statusText.textContent = `Prawie gotowe... ${Math.round(progress)}%`;
        } else {
            statusText.textContent = `Jeszcze chwilę... ${Math.round(progress)}%`;
        }
        counter.textContent = `Upłynęło: ${seconds}s (każdy news wymaga wywołania AI)`;
    }, 1000);

    try {
        // Use AbortController for timeout (3 minutes max)
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 180000);

        const response = await fetch('/admin/zopk/news/evaluate-ai', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify({ limit: 20 }),  // Reduced limit for faster response
            signal: controller.signal
        });

        clearTimeout(timeoutId);
        clearInterval(progressInterval);
        progressFill.style.width = '100%';

        const data = await response.json();

        // Switch to result view
        document.getElementById('aiEvalProgress').style.display = 'none';
        document.getElementById('aiEvalResult').style.display = 'block';

        const resultIcon = document.getElementById('aiResultIcon');
        const resultTitle = document.getElementById('aiResultTitle');
        const resultStats = document.getElementById('aiResultStats');

        if (data.success) {
            resultIcon.textContent = '✓';
            resultIcon.className = 'modal-icon success';
            resultTitle.textContent = 'Ocena zakończona!';
            resultStats.innerHTML = `
                <div class="ai-stat-item success">
                    <div class="value">${data.relevant_count}</div>
                    <div class="label">Pasuje do ZOP Kaszubia</div>
                </div>
                <div class="ai-stat-item danger">
                    <div class="value">${data.not_relevant_count}</div>
                    <div class="label">Nie pasuje</div>
                </div>
                <div class="ai-stat-item warning">
                    <div class="value">${data.total_evaluated}</div>
                    <div class="label">Ocenionych</div>
                </div>
                <p style="text-align: center; margin-top: var(--spacing-md); color: var(--text-secondary);">
                    Odświeżam stronę za 2 sekundy...
                </p>
            `;
            // Auto-reload after showing results
            setTimeout(() => location.reload(), 2000);
        } else {
            resultIcon.textContent = '✗';
            resultIcon.className = 'modal-icon error';
            resultTitle.textContent = 'Wystąpił błąd';
            resultStats.innerHTML = `<p style="text-align: center; color: var(--danger);">${data.error}</p>`;
            btn.disabled = false;
            btn.querySelector('.stat-label').textContent = 'AI: Oceń ponownie';
        }
    } catch (error) {
        clearInterval(progressInterval);

        document.getElementById('aiEvalProgress').style.display = 'none';
        document.getElementById('aiEvalResult').style.display = 'block';

        const resultIcon = document.getElementById('aiResultIcon');
        const resultTitle = document.getElementById('aiResultTitle');
        const resultStats = document.getElementById('aiResultStats');

        resultIcon.textContent = '✗';
        resultIcon.className = 'modal-icon error';

        // Check if timeout
        if (error.name === 'AbortError') {
            resultTitle.textContent = 'Przekroczono limit czasu';
            resultStats.innerHTML = `<p style="text-align: center; color: var(--danger);">
                Przetwarzanie trwało zbyt długo (>3 min).<br>
                Spróbuj ponownie lub sprawdź logi serwera.
            </p>`;
        } else {
            resultTitle.textContent = 'Błąd połączenia';
            resultStats.innerHTML = `<p style="text-align: center; color: var(--danger);">${error.message}</p>`;
        }

        btn.disabled = false;
        btn.querySelector('.stat-label').textContent = 'AI: Oceń ponownie';
    }
}

// Re-evaluate items missing scores (upgrade to 1-5 stars)
async function reevaluateScores() {
    const btn = document.getElementById('aiRescoreBtn');
    if (!btn) return;

    // Show modal for re-evaluation
    document.getElementById('aiEvalModal').classList.add('active');
    document.getElementById('aiEvalConfirm').style.display = 'none';
    document.getElementById('aiEvalProgress').style.display = 'block';
    document.getElementById('aiEvalResult').style.display = 'none';

    const progressBar = document.getElementById('aiProgressFill');
    const progressStatus = document.getElementById('aiProgressStatus');

    btn.disabled = true;
    btn.querySelector('.stat-label').textContent = 'AI pracuje...';

    // Simulated progress for better UX
    let progress = 0;
    let startTime = Date.now();
    const progressInterval = setInterval(() => {
        const elapsed = Math.floor((Date.now() - startTime) / 1000);
        if (progress < 90) {
            progress += Math.random() * 3;
            progressBar.style.width = Math.min(progress, 90) + '%';
        }
        progressStatus.textContent = `AI dodaje gwiazdki... (${elapsed}s)`;
    }, 500);

    try {
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 180000);

        const response = await fetch('/admin/zopk/news/reevaluate-scores', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify({ limit: 30 }),
            signal: controller.signal
        });

        clearTimeout(timeoutId);
        clearInterval(progressInterval);

        const data = await response.json();

        progressBar.style.width = '100%';

        document.getElementById('aiEvalProgress').style.display = 'none';
        document.getElementById('aiEvalResult').style.display = 'block';

        const resultIcon = document.getElementById('aiResultIcon');
        const resultTitle = document.getElementById('aiResultTitle');
        const resultStats = document.getElementById('aiResultStats');

        if (data.success) {
            resultIcon.textContent = '⭐';
            resultIcon.className = 'modal-icon success';
            resultTitle.textContent = 'Gwiazdki dodane!';
            resultStats.innerHTML = `
                <div style="display: flex; gap: 20px; justify-content: center; margin-bottom: var(--spacing-md);">
                    <div><strong>${data.total_evaluated}</strong><br><small>Ocenionych</small></div>
                    <div style="color: var(--success);"><strong>${data.relevant_count}</strong><br><small>Pasuje</small></div>
                    <div style="color: var(--danger);"><strong>${data.not_relevant_count}</strong><br><small>Nie pasuje</small></div>
                </div>
                <p style="text-align: center; color: var(--text-secondary);">${data.message}</p>
            `;
            setTimeout(() => location.reload(), 2000);
        } else {
            resultIcon.textContent = '✗';
            resultIcon.className = 'modal-icon error';
            resultTitle.textContent = 'Wystąpił błąd';
            resultStats.innerHTML = `<p style="text-align: center; color: var(--danger);">${data.error}</p>`;
            btn.disabled = false;
            btn.querySelector('.stat-label').textContent = 'AI: Spróbuj ponownie';
        }
    } catch (error) {
        clearInterval(progressInterval);
        document.getElementById('aiEvalProgress').style.display = 'none';
        document.getElementById('aiEvalResult').style.display = 'block';

        const resultIcon = document.getElementById('aiResultIcon');
        const resultTitle = document.getElementById('aiResultTitle');
        const resultStats = document.getElementById('aiResultStats');

        resultIcon.textContent = '✗';
        resultIcon.className = 'modal-icon error';
        resultTitle.textContent = 'Błąd połączenia';
        resultStats.innerHTML = `<p style="text-align: center; color: var(--danger);">${error.message}</p>`;

        btn.disabled = false;
        btn.querySelector('.stat-label').textContent = 'AI: Spróbuj ponownie';
    }
}

// Re-evaluate low score news (1-2★) with key topics (Via Pomerania, NORDA, etc.)
async function reevaluateLowScores() {
    const btn = document.getElementById('aiReevalLowBtn');
    if (!btn) return;

    // Show modal for re-evaluation
    document.getElementById('aiEvalModal').classList.add('active');
    document.getElementById('aiEvalConfirm').style.display = 'none';
    document.getElementById('aiEvalProgress').style.display = 'block';
    document.getElementById('aiEvalResult').style.display = 'none';

    const progressBar = document.getElementById('aiProgressFill');
    const progressStatus = document.getElementById('aiProgressStatus');

    btn.disabled = true;
    btn.querySelector('.stat-label').textContent = 'Re-ewaluacja...';

    // Simulated progress for better UX
    let progress = 0;
    let startTime = Date.now();
    const progressInterval = setInterval(() => {
        const elapsed = Math.floor((Date.now() - startTime) / 1000);
        if (progress < 90) {
            progress += Math.random() * 3;
            progressBar.style.width = Math.min(progress, 90) + '%';
        }
        progressStatus.textContent = `Re-ewaluacja newsów z Via Pomerania, NORDA... (${elapsed}s)`;
    }, 500);

    try {
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 180000);

        const response = await fetch('/admin/zopk/news/reevaluate-low-scores', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify({ limit: 50 }),
            signal: controller.signal
        });

        clearTimeout(timeoutId);
        clearInterval(progressInterval);

        const data = await response.json();

        progressBar.style.width = '100%';

        document.getElementById('aiEvalProgress').style.display = 'none';
        document.getElementById('aiEvalResult').style.display = 'block';

        const resultIcon = document.getElementById('aiResultIcon');
        const resultTitle = document.getElementById('aiResultTitle');
        const resultStats = document.getElementById('aiResultStats');

        if (data.success) {
            resultIcon.textContent = '🔄';
            resultIcon.className = 'modal-icon success';
            resultTitle.textContent = 'Re-ewaluacja zakończona!';

            // Build details list if available
            let detailsHtml = '';
            if (data.details && data.details.length > 0) {
                detailsHtml = `
                    <div style="max-height: 200px; overflow-y: auto; margin-top: var(--spacing-md); text-align: left; font-size: var(--font-size-sm);">
                        ${data.details.map(d => `
                            <div style="padding: 4px 0; border-bottom: 1px solid var(--border);">
                                <span style="color: ${d.change === 'upgraded' ? 'var(--success)' : d.change === 'downgraded' ? 'var(--danger)' : 'var(--text-secondary)'};">
                                    ${d.old_score}★ → ${d.new_score}★
                                </span>
                                ${d.title}...
                            </div>
                        `).join('')}
                    </div>
                `;
            }

            resultStats.innerHTML = `
                <div style="display: flex; gap: 20px; justify-content: center; margin-bottom: var(--spacing-md);">
                    <div><strong>${data.total_evaluated}</strong><br><small>Ocenionych</small></div>
                    <div style="color: var(--success);"><strong>${data.upgraded}</strong><br><small>⬆️ Podwyższono</small></div>
                    <div style="color: var(--danger);"><strong>${data.downgraded}</strong><br><small>⬇️ Obniżono</small></div>
                    <div style="color: var(--text-secondary);"><strong>${data.unchanged}</strong><br><small>Bez zmian</small></div>
                </div>
                <p style="text-align: center; color: var(--text-secondary);">${data.message}</p>
                ${detailsHtml}
            `;

            if (data.upgraded > 0 || data.downgraded > 0) {
                setTimeout(() => location.reload(), 3000);
            }
        } else {
            resultIcon.textContent = '✗';
            resultIcon.className = 'modal-icon error';
            resultTitle.textContent = 'Wystąpił błąd';
            resultStats.innerHTML = `<p style="text-align: center; color: var(--danger);">${data.error}</p>`;
            btn.disabled = false;
            btn.querySelector('.stat-label').textContent = 'Re-ewaluuj niskie oceny';
        }
    } catch (error) {
        clearInterval(progressInterval);
        document.getElementById('aiEvalProgress').style.display = 'none';
        document.getElementById('aiEvalResult').style.display = 'block';

        const resultIcon = document.getElementById('aiResultIcon');
        const resultTitle = document.getElementById('aiResultTitle');
        const resultStats = document.getElementById('aiResultStats');

        resultIcon.textContent = '✗';
        resultIcon.className = 'modal-icon error';
        resultTitle.textContent = 'Błąd połączenia';
        resultStats.innerHTML = `<p style="text-align: center; color: var(--danger);">${error.message}</p>`;

        btn.disabled = false;
        btn.querySelector('.stat-label').textContent = 'Re-ewaluuj niskie oceny';
    }
}

// Close modal on click outside
document.getElementById('aiEvalModal').addEventListener('click', function(e) {
    if (e.target === this) {
        closeAiEvalModal();
    }
});

// Source names mapping for progress display
const SOURCE_NAMES = {
    'brave': '🔍 Brave Search API',
    'trojmiasto': '📰 trojmiasto.pl',
    'dziennik_baltycki': '📰 Dziennik Bałtycki',
    'gov_mon': '🏛️ Ministerstwo Obrony Narodowej',
    'gov_przemysl': '🏛️ Min. Rozwoju i Technologii',
    'google_news_zopk': '📡 Google News (ZOP Kaszubia)',
    'google_news_offshore': '📡 Google News (offshore)',
    'google_news_nuclear': '📡 Google News (elektrownia jądrowa)',
    'google_news_samsonowicz': '📡 Google News (Samsonowicz)',
    'google_news_kongsberg': '📡 Google News (Kongsberg)',
    // New local media sources
    'google_news_norda_fm': '📻 Norda FM',
    'google_news_ttm': '📺 Twoja Telewizja Morska',
    'google_news_nadmorski24': '📰 Nadmorski24.pl',
    'google_news_samsonowicz_fb': '👤 Facebook (Samsonowicz)',
    'google_news_norda': '📡 Google News (Norda Biznes)',
    'google_news_spoko': '📡 Google News (Spoko Gospodarcze)'
};

const ALL_SOURCES = Object.keys(SOURCE_NAMES);

async function searchNews() {
    const btn = document.getElementById('searchBtn');
    const progressContainer = document.getElementById('progressContainer');
    const progressBar = document.getElementById('progressBar');
    const progressStatus = document.getElementById('progressStatus');
    const progressPercent = document.getElementById('progressPercent');
    const progressPhases = document.getElementById('progressPhases');
    const progressSteps = document.getElementById('progressSteps');
    const resultsContainer = document.getElementById('searchResultsContainer');
    const resultsSummary = document.getElementById('searchResultsSummary');
    const autoApprovedSection = document.getElementById('autoApprovedSection');
    const autoApprovedList = document.getElementById('autoApprovedList');
    const query = document.getElementById('searchQuery').value;

    // Process phases definition
    const PHASES = [
        { id: 'search', icon: '🔍', label: 'Wyszukiwanie' },
        { id: 'filter', icon: '🚫', label: 'Filtrowanie' },
        { id: 'ai', icon: '🤖', label: 'Analiza AI' },
        { id: 'save', icon: '💾', label: 'Zapisywanie' }
    ];

    // Reset UI
    btn.disabled = true;
    btn.textContent = 'Szukam...';
    resultsContainer.style.display = 'none';
    autoApprovedSection.style.display = 'none';
    progressContainer.classList.add('active');
    progressBar.style.width = '0%';
    progressBar.style.background = '';  // Reset color
    progressPercent.textContent = '0%';

    // Build progress phases UI
    progressPhases.innerHTML = PHASES.map(phase => `
        <div class="progress-phase pending" id="phase-${phase.id}">
            <span class="progress-phase-icon">${phase.icon}</span>
            <span>${phase.label}</span>
        </div>
    `).join('');

    // Build initial progress steps (will be populated from process_log)
    progressSteps.innerHTML = '<div class="progress-step active"><span class="progress-step-icon">⏳</span><span>Inicjalizacja...</span></div>';

    // Simulate progress phases while waiting for API
    let currentPhaseIdx = 0;
    const phaseMessages = [
        'Przeszukuję źródła (Brave API + RSS)...',
        'Filtruję wyniki (blacklist, słowa kluczowe)...',
        'Analiza AI (Gemini ocenia artykuły)...',
        'Zapisuję do bazy wiedzy...'
    ];

    const progressInterval = setInterval(() => {
        if (currentPhaseIdx < PHASES.length) {
            // Update phase UI
            PHASES.forEach((phase, idx) => {
                const el = document.getElementById(`phase-${phase.id}`);
                if (el) {
                    el.classList.remove('pending', 'active', 'completed');
                    if (idx < currentPhaseIdx) el.classList.add('completed');
                    else if (idx === currentPhaseIdx) el.classList.add('active');
                    else el.classList.add('pending');
                }
            });

            progressStatus.textContent = phaseMessages[currentPhaseIdx];
            const percent = Math.round(((currentPhaseIdx + 1) / PHASES.length) * 80);
            progressBar.style.width = `${percent}%`;
            progressPercent.textContent = `${percent}%`;

            currentPhaseIdx++;
        }
    }, 2500);  // Each phase ~2.5s for realistic timing

    try {
        const response = await fetch('{{ url_for("api_zopk_search_news") }}', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify({ query: query })
        });

        clearInterval(progressInterval);

        const data = await response.json();

        if (data.success) {
            // Mark all phases as completed
            PHASES.forEach(phase => {
                const el = document.getElementById(`phase-${phase.id}`);
                if (el) {
                    el.classList.remove('pending', 'active');
                    el.classList.add('completed');
                }
            });

            progressBar.style.width = '100%';
            progressPercent.textContent = '100%';
            progressStatus.textContent = '✅ Wyszukiwanie zakończone!';

            // Display process log as steps
            if (data.process_log && data.process_log.length > 0) {
                // Show last few important steps
                const importantSteps = data.process_log.filter(log =>
                    log.step.includes('done') || log.step.includes('complete') || log.phase === 'complete'
                ).slice(-6);

                progressSteps.innerHTML = importantSteps.map(log => `
                    <div class="progress-step completed">
                        <span class="progress-step-icon">✓</span>
                        <span>${log.message}</span>
                        ${log.count > 0 ? `<span class="progress-step-count">${log.count}</span>` : ''}
                    </div>
                `).join('');
            }

            // Hide progress container after a moment
            setTimeout(() => {
                progressContainer.classList.remove('active');
            }, 1500);

            // Show results container
            resultsContainer.style.display = 'block';

            // Build summary stats
            resultsSummary.innerHTML = `
                <div class="summary-stat info">
                    <div class="value">${data.total_found || 0}</div>
                    <div class="label">Znaleziono</div>
                </div>
                <div class="summary-stat warning">
                    <div class="value">${(data.blacklisted || 0) + (data.keyword_filtered || 0)}</div>
                    <div class="label">Odfiltrowano</div>
                </div>
                <div class="summary-stat error">
                    <div class="value">${data.ai_rejected || 0}</div>
                    <div class="label">AI odrzucił</div>
                </div>
                <div class="summary-stat success">
                    <div class="value">${data.ai_approved || 0}</div>
                    <div class="label">AI zaakceptował</div>
                </div>
                <div class="summary-stat success">
                    <div class="value">${data.saved_new || 0}</div>
                    <div class="label">Nowe w bazie</div>
                </div>
            `;

            // Show auto-approved articles list
            if (data.auto_approved_articles && data.auto_approved_articles.length > 0) {
                autoApprovedSection.style.display = 'block';
                autoApprovedList.innerHTML = data.auto_approved_articles.map(article => {
                    const stars = '★'.repeat(article.score) + '☆'.repeat(5 - article.score);
                    return `
                        <div class="auto-approved-item">
                            <span class="stars">${stars}</span>
                            <span class="title">${article.title}</span>
                            <span class="source">${article.source || ''}</span>
                        </div>
                    `;
                }).join('');
            }

            // Show detailed statistics section
            const detailedStatsSection = document.getElementById('detailedStatsSection');
            const detailedStatsGrid = document.getElementById('detailedStatsGrid');
            const aiRejectedSection = document.getElementById('aiRejectedSection');
            const aiRejectedList = document.getElementById('aiRejectedList');

            // Build detailed statistics
            const detailedStats = [
                { label: 'Zapytanie', value: query || 'ZOP Kaszubia', icon: '🔍', type: 'info' },
                { label: 'Źródła przeszukane', value: `Brave API + RSS`, icon: '📡', type: 'info' },
                { label: 'Łącznie znaleziono', value: data.total_found || 0, icon: '📰', type: 'info' },
                { label: 'Zablokowane (blacklist)', value: data.blacklisted || 0, icon: '🚫', type: 'warning' },
                { label: 'Odfiltrowane (słowa kluczowe)', value: data.keyword_filtered || 0, icon: '🔤', type: 'warning' },
                { label: 'Przekazane do AI', value: data.sent_to_ai || 0, icon: '🤖', type: 'info' },
                { label: 'AI zaakceptował (3+★)', value: data.ai_approved || 0, icon: '✅', type: 'success' },
                { label: 'AI odrzucił (1-2★)', value: data.ai_rejected || 0, icon: '❌', type: 'error' },
                { label: 'Duplikaty (już w bazie)', value: data.duplicates || 0, icon: '🔄', type: 'info' },
                { label: 'Zapisano nowych', value: data.saved_new || 0, icon: '💾', type: 'success' },
                { label: 'Do bazy wiedzy', value: data.knowledge_entities_created || 0, icon: '🧠', type: 'success' },
                { label: 'Czas przetwarzania', value: data.processing_time ? `${data.processing_time.toFixed(1)}s` : '-', icon: '⏱️', type: 'info' }
            ];

            detailedStatsGrid.innerHTML = detailedStats.map(stat => `
                <div class="detailed-stat-item" style="
                    background: ${stat.type === 'success' ? '#dcfce7' : stat.type === 'error' ? '#fee2e2' : stat.type === 'warning' ? '#fef3c7' : '#f3f4f6'};
                    padding: var(--spacing-sm) var(--spacing-md);
                    border-radius: var(--radius);
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                ">
                    <span style="display: flex; align-items: center; gap: var(--spacing-xs);">
                        <span>${stat.icon}</span>
                        <span style="font-size: var(--font-size-sm);">${stat.label}</span>
                    </span>
                    <strong style="color: ${stat.type === 'success' ? '#166534' : stat.type === 'error' ? '#991b1b' : stat.type === 'warning' ? '#92400e' : '#374151'};">
                        ${stat.value}
                    </strong>
                </div>
            `).join('');
            detailedStatsSection.style.display = 'block';

            // Show AI rejected articles if any
            if (data.ai_rejected_articles && data.ai_rejected_articles.length > 0) {
                aiRejectedSection.style.display = 'block';
                aiRejectedList.innerHTML = data.ai_rejected_articles.map(article => {
                    const stars = '★'.repeat(article.score || 1) + '☆'.repeat(5 - (article.score || 1));
                    return `
                        <div class="ai-rejected-item" style="
                            padding: var(--spacing-xs) var(--spacing-sm);
                            border-bottom: 1px solid #fee2e2;
                            font-size: var(--font-size-sm);
                            display: flex;
                            gap: var(--spacing-sm);
                            align-items: center;
                        ">
                            <span style="color: #f59e0b;">${stars}</span>
                            <span style="flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">${article.title}</span>
                            <span style="color: var(--text-secondary); font-size: var(--font-size-xs);">${article.source || ''}</span>
                        </div>
                    `;
                }).join('');
            }

            // Scroll to results for better visibility
            resultsContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });

        } else {
            // Error handling
            progressBar.style.width = '100%';
            progressBar.style.background = '#fca5a5';
            progressStatus.textContent = 'Błąd wyszukiwania';

            PHASES.forEach(phase => {
                const el = document.getElementById(`phase-${phase.id}`);
                if (el) el.classList.remove('active');
            });

            progressSteps.innerHTML = `
                <div class="progress-step" style="color: #fca5a5;">
                    <span class="progress-step-icon">✗</span>
                    <span>Błąd: ${data.error}</span>
                </div>
            `;
            btn.disabled = false;
            btn.textContent = 'Szukaj artykułów';
        }
    } catch (error) {
        clearInterval(progressInterval);
        progressBar.style.width = '100%';
        progressBar.style.background = '#fca5a5';
        progressStatus.textContent = 'Błąd połączenia';

        progressSteps.innerHTML = `
            <div class="progress-step" style="color: #fca5a5;">
                <span class="progress-step-icon">✗</span>
                <span>Błąd połączenia: ${error.message}</span>
            </div>
        `;
        btn.disabled = false;
        btn.textContent = 'Szukaj artykułów';
    }
}

// Close modal on click outside
document.getElementById('addNewsModal').addEventListener('click', function(e) {
    if (e.target === this) {
        closeAddNewsModal();
    }
});

// ===========================================
// AI Knowledge Base Functions
// ===========================================

async function loadKnowledgeStats() {
    try {
        const response = await fetch('/admin/zopk/knowledge/stats');
        const data = await response.json();

        if (data.success) {
            document.getElementById('knowledge-stats-loading').style.display = 'none';
            document.getElementById('knowledge-stats-content').style.display = 'block';

            // Scraping stats
            document.getElementById('kb-total-approved').textContent = data.articles?.total_approved || 0;
            document.getElementById('kb-scraped').textContent = data.articles?.scraped || 0;
            document.getElementById('kb-pending-scrape').textContent = data.articles?.pending_scrape || 0;

            // Knowledge base stats
            document.getElementById('kb-total-chunks').textContent = data.knowledge_base?.total_chunks || 0;
            document.getElementById('kb-total-facts').textContent = data.knowledge_base?.total_facts || 0;
            document.getElementById('kb-total-entities').textContent = data.knowledge_base?.total_entities || 0;

            // Embeddings stats
            document.getElementById('kb-with-embeddings').textContent = data.knowledge_base?.chunks_with_embeddings || 0;
            document.getElementById('kb-pending-embeddings').textContent = data.knowledge_base?.chunks_without_embeddings || 0;

            // Top entities
            if (data.top_entities && data.top_entities.length > 0) {
                document.getElementById('top-entities-section').style.display = 'block';
                const list = document.getElementById('top-entities-list');
                list.innerHTML = data.top_entities.map(e =>
                    `<span class="entity-pill entity-${e.type}">${e.name} <small>(${e.mentions})</small></span>`
                ).join('');
            }
        } else {
            throw new Error(data.error || 'Unknown error');
        }
    } catch (error) {
        console.error('Error loading knowledge stats:', error);
        document.getElementById('knowledge-stats-loading').style.display = 'none';
        document.getElementById('knowledge-stats-error').style.display = 'block';
        document.getElementById('knowledge-stats-error').textContent = `Błąd: ${error.message}`;
    }
}

// ===========================================
// AI Operations Modal Functions
// ===========================================

let aiOpsEventSource = null;
let aiOpsLogEntries = 0;

function openAiOpsModal(title, icon) {
    const modal = document.getElementById('aiOpsModal');
    document.getElementById('aiOpsTitle').textContent = title;
    document.getElementById('aiOpsIcon').textContent = icon;
    document.getElementById('aiOpsIcon').classList.add('spinning');

    // Reset state
    document.getElementById('aiOpsProgressFill').style.width = '0%';
    document.getElementById('aiOpsPercent').textContent = '0%';
    document.getElementById('aiOpsCounter').textContent = '0 / 0';
    document.getElementById('aiOpsCurrentText').textContent = 'Inicjalizacja...';
    document.getElementById('aiOpsLog').innerHTML = '';
    document.getElementById('aiOpsSummary').style.display = 'none';
    document.getElementById('aiOpsActions').style.display = 'none';
    document.getElementById('aiOpsCloseBtn').style.display = 'none';
    document.getElementById('aiOpsCurrentOp').style.display = 'flex';
    aiOpsLogEntries = 0;
    document.getElementById('aiOpsLogCount').textContent = '0 wpisów';

    modal.classList.add('active');
}

function closeAiOpsModal() {
    const modal = document.getElementById('aiOpsModal');
    modal.classList.remove('active');

    // Close SSE connection if active
    if (aiOpsEventSource) {
        aiOpsEventSource.close();
        aiOpsEventSource = null;
    }
}

function addAiOpsLogEntry(status, message) {
    const log = document.getElementById('aiOpsLog');
    const time = new Date().toLocaleTimeString('pl-PL', { hour: '2-digit', minute: '2-digit', second: '2-digit' });

    const entry = document.createElement('div');
    entry.className = `log-entry ${status}`;
    entry.innerHTML = `
        <span class="log-time">${time}</span>
        <span class="log-message">${message}</span>
    `;

    log.appendChild(entry);
    log.scrollTop = log.scrollHeight;

    aiOpsLogEntries++;
    document.getElementById('aiOpsLogCount').textContent = `${aiOpsLogEntries} wpisów`;
}

function updateAiOpsProgress(data) {
    // Update progress bar
    if (data.percent !== undefined) {
        document.getElementById('aiOpsProgressFill').style.width = `${data.percent}%`;
        document.getElementById('aiOpsPercent').textContent = `${Math.round(data.percent)}%`;
    }

    // Update counter
    if (data.current !== undefined && data.total !== undefined) {
        document.getElementById('aiOpsCounter').textContent = `${data.current} / ${data.total}`;
    }

    // Update current operation text
    if (data.message) {
        document.getElementById('aiOpsCurrentText').textContent = data.message;
    }

    // Add log entry
    if (data.status && data.message) {
        addAiOpsLogEntry(data.status, data.message);
    }
}

function completeAiOpsModal(data) {
    // Stop spinning
    document.getElementById('aiOpsIcon').classList.remove('spinning');
    document.getElementById('aiOpsIcon').textContent = data.status === 'error' ? '❌' : '✅';
    document.getElementById('aiOpsTitle').textContent = data.status === 'error' ? 'Błąd operacji' : 'Operacja zakończona';

    // Hide current operation
    document.getElementById('aiOpsCurrentOp').style.display = 'none';

    // Show summary
    const details = data.details || {};
    document.getElementById('aiOpsSummarySuccess').textContent = details.success || details.scraped || 0;
    document.getElementById('aiOpsSummaryFailed').textContent = details.failed || 0;

    if (details.skipped !== undefined) {
        document.getElementById('aiOpsSummarySkippedRow').style.display = 'flex';
        document.getElementById('aiOpsSummarySkipped').textContent = details.skipped;
    }

    if (details.processing_time) {
        document.getElementById('aiOpsSummaryTime').textContent = `${details.processing_time}s`;
    }

    document.getElementById('aiOpsSummary').style.display = 'grid';
    document.getElementById('aiOpsActions').style.display = 'flex';
    document.getElementById('aiOpsCloseBtn').style.display = 'block';
}

function startSSEOperation(endpoint, title, icon, limit) {
    openAiOpsModal(title, icon);

    const url = `${endpoint}?limit=${limit}`;
    aiOpsEventSource = new EventSource(url);

    aiOpsEventSource.onmessage = function(event) {
        const data = JSON.parse(event.data);

        if (data.status === 'complete' || data.status === 'error') {
            aiOpsEventSource.close();
            aiOpsEventSource = null;
            completeAiOpsModal(data);
        } else {
            updateAiOpsProgress(data);
        }
    };

    aiOpsEventSource.onerror = function(event) {
        console.error('SSE error:', event);
        aiOpsEventSource.close();
        aiOpsEventSource = null;
        completeAiOpsModal({ status: 'error', message: 'Błąd połączenia', details: {} });
    };
}

// ===========================================
// AI Knowledge Base Functions (with SSE)
// ===========================================

async function scrapeContent() {
    const confirmed = await showConfirm(
        'Czy chcesz rozpocząć scrapowanie treści artykułów?<br><br>' +
        '<small>Proces pobierze pełną treść z zatwierdzonych newsów które jeszcze nie mają treści.<br>' +
        'Postęp będzie wyświetlany na żywo.</small>',
        { icon: '📄', title: 'Scraping treści', okText: 'Rozpocznij', okClass: 'btn-primary' }
    );

    if (!confirmed) return;

    startSSEOperation('/admin/zopk/news/scrape-content/stream', 'Scraping treści artykułów', '📄', 30);
}

async function extractKnowledge() {
    const confirmed = await showConfirm(
        'Czy chcesz uruchomić ekstrakcję wiedzy przez AI?<br><br>' +
        '<small>Gemini AI przeanalizuje zescrapowane artykuły i wyekstrahuje:<br>' +
        '• Chunks (fragmenty tekstu)<br>' +
        '• Fakty (daty, liczby, decyzje)<br>' +
        '• Encje (firmy, osoby, projekty)<br><br>' +
        'Postęp będzie wyświetlany na żywo.</small>',
        { icon: '🤖', title: 'Ekstrakcja wiedzy', okText: 'Uruchom AI', okClass: 'btn-primary' }
    );

    if (!confirmed) return;

    startSSEOperation('/admin/zopk/knowledge/extract/stream', 'Ekstrakcja wiedzy (Gemini AI)', '🤖', 10);
}

async function generateEmbeddings() {
    const confirmed = await showConfirm(
        'Czy chcesz wygenerować embeddingi dla semantic search?<br><br>' +
        '<small>Google Text Embedding API przekształci tekst w wektory 768-wymiarowe.<br>' +
        'Embeddingi umożliwiają inteligentne wyszukiwanie w bazie wiedzy.<br><br>' +
        'Postęp będzie wyświetlany na żywo.</small>',
        { icon: '🔍', title: 'Generowanie embeddingów', okText: 'Generuj', okClass: 'btn-primary' }
    );

    if (!confirmed) return;

    startSSEOperation('/admin/zopk/knowledge/embeddings/stream', 'Generowanie embeddingów', '🔍', 50);
}

// Keep old code for backward compatibility (non-SSE version - can be removed later)
async function scrapeContentOld() {
    const btn = document.getElementById('scrapeBtn');
    const originalContent = btn.innerHTML;

    btn.disabled = true;
    btn.innerHTML = '<span class="spinner-small"></span>';

    try {
        const response = await fetch('/admin/zopk/news/scrape-content', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken },
            body: JSON.stringify({ limit: 30 })
        });
        const data = await response.json();

        if (data.success) {
            showToast(data.message || `Zescrapowano ${data.scraped || 0} artykułów`, 'success');
            loadKnowledgeStats();
        } else {
            showToast(data.error || 'Błąd scrapowania', 'error');
        }
    } catch (error) {
        showToast(`Błąd: ${error.message}`, 'error');
    } finally {
        btn.disabled = false;
        btn.innerHTML = originalContent;
    }
}

async function extractKnowledgeOld() {
    const btn = document.getElementById('extractBtn');
    const originalContent = btn.innerHTML;

    btn.disabled = true;
    btn.innerHTML = '<span class="spinner-small"></span>';

    try {
        const response = await fetch('/admin/zopk/knowledge/extract', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken },
            body: JSON.stringify({ limit: 10 })
        });
        const data = await response.json();

        if (data.success) {
            showToast(data.message || 'Ekstrakcja zakończona', 'success');
            loadKnowledgeStats();
        } else {
            showToast(data.error || 'Błąd ekstrakcji', 'error');
        }
    } catch (error) {
        showToast(`Błąd: ${error.message}`, 'error');
    } finally {
        btn.disabled = false;
        btn.innerHTML = originalContent;
    }
}

async function generateEmbeddingsOld() {
    const btn = document.getElementById('embeddingsBtn');
    const originalContent = btn.innerHTML;

    btn.disabled = true;
    btn.innerHTML = '<span class="spinner-small"></span>';

    try {
        const response = await fetch('/admin/zopk/knowledge/embeddings', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken },
            body: JSON.stringify({ limit: 50 })
        });
        const data = await response.json();

        if (data.success) {
            showToast(data.message || 'Embeddingi wygenerowane', 'success');
            loadKnowledgeStats();
        } else {
            showToast(data.error || 'Błąd generowania', 'error');
        }
    } catch (error) {
        showToast(`Błąd: ${error.message}`, 'error');
    } finally {
        btn.disabled = false;
        btn.innerHTML = originalContent;
    }
}

// Load knowledge stats on page load
document.addEventListener('DOMContentLoaded', loadKnowledgeStats);
{% endblock %}
